О б р а б о т к а

м а с с и в о в

Обработка строк.

  1. В мнемонике команд обработки строк всегда содержится буква S (String — строка). Она является последней или предпоследней буквой.
  2. Содержимое строки для микропроцессора НЕ имеет никакого значения. Это могут быть символы, числа и все, что угодно. Основное, что имеет значение, — это длина операнда.
  3. Строка в базовом Ассемблере может обрабатываться побайтно (BYTEпоследняя буква в команде будет В) или пословно (WORDпоследняя буква в команде будет W).
  4. Строка может обрабатываться группой (цепочкой), тогда перед командой появляется префикс REPx (REPeat — повторить). Количество повторений должно находиться в регистре СХ. Этот префикс алгоритмически подобен команде LOOPx.
  5. Строка-приемник должна находиться обязательно в дополнительном сегменте памяти ES со смещением DI (адресация < ES:DI > ).
  6. Строка-источник должна находиться в сегменте данных DS со смещением SI (адресация < DS:SI > ). Допускается замена регистра сегмента DS с помощью префикса замены сегмента.
  7. В процессе циклического выполнения команд указатели SI и DI автоматически модифицируются в зависимости от длины элемента строки и значения флага направления DF:
    • Если < DF >=0, значения SI и DI увеличиваются (строка обрабатывается слева направо — в сторону больших адресов).
    • Если < DF >=1, значения SI и DI уменьшаются (строка обрабатывается справа налево — в сторону меньших адресов).
  8. Флаг направления DF очищается или устанавливается, соответственно, командами CLD или STD.
  9. Длина строки в базовом Ассемблере <= 64К байт.
Команда Назначение Алгоритм работы
Команды пересылки MOVSx - переслать один байт или одно слово из одной области памяти в другую
MOVS приемник, источник Копирование строки Приемник ⇐ Источник
MOVSB Копирование строки байтов [DI] ⇐ [SI]
MOVSW Копирование строки слов
Команды сравнения CMPSx - сравнить содержимое двух областей памяти, размером в один байт или в одно слово
CMPS приемник, источник Сравнение строки Приемник ~ Источник
CMPSB Сравнение строк байтов [DI] ~ [SI]
CMPSW Сравнение строк слов
Команды сканирования SCASx - сравнить содержимое регистра AL или AX с содержимым памяти
SCAS приемник Сканирование строки Приемник ~ AX(или AL)
SCASB Сканирование строки байтов [DI] ~ AL
SCASW Сравнение строки слов [DI] ~ AX
Команды загрузки LODSx - загрузить из памяти один байт в регистр AL или одно слово в регистр AX
LODS источник Чтение из строки Источник ⇒ AX(AL)
LODSB Чтение байта из строки [SI] ⇒ AL
LODSW Чтение слова из строки [SI] ⇒ AX
Команды сохранения STOSx - записать содержимое регистра AL или AX в память
STOS приемник Записать в строку AX(AL) ⇒ Приемник
STOSB Записать байта в строку AL ⇒ [DI]
STOSW Чтение слова из строки AX ⇒ [DI]
Префиксы повторений REPx
REP Повторять команду
REPE / REPZ Повторять команду, пока равно (флаг ZF = 1)
REPNE / REPNZ Повторять команду, пока НЕ равно (флаг ZF = 0)

В примере выполняется пересылка 20 байт из STRING1 в STRING2.
Предположим, что оба регистра DS и ES инициализированы адресом сегмента данных:

STRING1 DB 20 DUP('*')
STRING2 DB 20 DUP(' ')
...
CLD ; Сброс флага DF
MOV CX,20 ; Счетчик на 20 байт
LEA DI,STRING2 ; Адрес области "куда"
LEA SI,STRING1 ; Адрес области "откуда"
REP MOVSB ; Переслать данные

Обработка одномерных массивов.

Для того чтобы обрабатывать массив, нужно знать, где он хранится (его начальный адрес), длину его элементов и их число. Как и в языке C/C++, имя массива в Ассемблере является также и его начальным адресом.

Режим адресации с индексацией вида имя_массива[регистр_индекс] позволяет обрабатывать каждый элемент массива. В качестве регистра__индекса можно брать любой допустимый для косвенной адресации регистр, например, регистр ВХ.

Основные характеристики вещественного массива float ArrF[5] в Ассемблере.

Байты в ОЗУ 1 2 3 4 5 6 7 8 ... 17 18 19 20
Индекс - переменная (i) 0 1 ... 4
Элементы массива (значения) ArrF[0] ArrF[1] ... ArrF[4]
Адреса (смещения) ArrF ArrF+1 ArrF+2 ArrF+3 ... ... ArrF+16 ArrF+17 ArrF+18 ArrF+19
Индекс - регистр (смещение) BX0 BX0+4 ... BX0+4*i

В общем случае, если взять в качестве индекс-регистра регистр ВХ, доступ к любому элементу одномерного массива Array [i] длины Larray подчиняется в Ассемблере следующей закономерности:
Array[i] ⇒ Аггау + ВХj = Array[BXj],
где
ВХj = ВХ0 + Larray * i = ВХj-1 + Larray;
ВХ0 =0; i=0, ... , n-1; n - длина массива Array.

model large,С
; CopyRight by Голубь Н.Г., 2001
LOCALS
.CODE
EXTRN С A:Word, n:Word, S:DWord
PUBLIC С SummA

; Синонимы:
a EQU A[BX]
s0 EQU WORD PTR S ; мл, часть суммы
s2 EQU WORD PTR S+2 ; ст. часть суммы
SummA Proc С far
XOR BX,BX ; смещение < ВХ >=0
XOR SI,SI ; мл. часть суммы
XOR DI, DI ; ст. часть суммы
MOV CX, N
JCXZ @@4
@01:
MOV AX , A
CWD
ADD SI, AX ; длинное сложение
ADC DI,DX
; переход к след. элементу массива А
INC BХ
INC BХ ; изменение смещения BX = BX+2
LOOP @01
@04:
MOV sO,SI
MOV s2,DX
RET.
SummA EndP
END

Двумерные массивы.

Для двухмерных массивов (матриц) идея будет та же самая, только нужно определиться, как такой массив будет располагаться в оперативной памяти: по строкам или по столбцам (память-то линейная!). Соответственно, и индексных регистров тоже будет два. А также два цикла: внешний и внутренний. Значит, и вычислений прибавится.

Например, пусть имеется некая матрица Matr[M] [N] и в памяти она располагается по строкам: сначала N элементов первой строки, потом N второй строки и т.д.
Длину элемента обозначим Larr.
Тогда адрес элемента Matr[I,j] будет равен Matr+N*i* Larray+j, где i=0, ... ,M-1; j=0, ... , N-1. Выделим в Ассемблере для хранения величины N*i* Larray регистр ВХ, а для j регистр SI (или DI). Тогда Matr[BX] будет означать начальный адрес строки i, a Matr[BX][SI] (Matr[BX+SI] или Matr+[BX+SI] — эти три записи равнозначны) — адрес элемента j в этой строке, т.е.
Matr[i j] - Matr[BX] [SI]

Основные характеристики целоцисленной матрицы A[10][5] в Ассемблере.

Байты 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ... 97 98 99 100
Столбцы 0 1 2 3 4 0 1 ... 3 4
Индекс - регистр SI 0 +2 +4 +6 +8 0 +2 ... +6 +8
Строки (i) 0 1 1 9
Индекс - регистр BX 0 +10 +(10*1) +(10*9)=+90

MODEL LARGE,С ; CopyRight by Голубь H.Г., 2001
; Сумма scex элементов матрицы A[] [N]

LOCALS @@
.CODE
EXTRN С A: Word, m: Word, n: Word, S:DWord
N DW 10 ; 2(длина int)*N=2*5 !!!
PUBLIC C SummA2
a EQU A[BX][SI] ; Двойная индексация !!!
s0 EQU WORD PTR S ; мл, часть суммы
s2 EQU WORD PTR S+2 ; ст. часть суммы
SummA2 Proc С far
XOR BX,BX ; смещение < ВХ >=0 (по строкам)
MOV s0,0
MOV s2,0

; цикл по строкам (внешний)
MOV CX,m
JCXZ @@4
@@1:

; сохранить счетчик ВНЕШНЕГО цикла в стеке
PUSH CX
; цикл по столбцам (внутренний)
XOR SI,SI ; смещение < SI >=0 (по столбцам)
MOV CX,n
JCXZ @@4
@@2:
MOV AX, a
CWD
ADD s0, AX ; длинное сложение
ADC s2, DX
; переход к след. элементу массива А
INC SI
INC SI ; +2(int!!!)
; изменение смещения < BX > = < BX > + 2*N
; переход на следующую строку

ADD BX, N
; восстановить счетчик ВНЕШНЕГО цикла из стека
POP CX
LOOP @@1
@@4:
RET
SummA2 ENDP
END

Лабораторная работа №4

Программирование на Машинно-Ориентированных Языках.
Преподаватель: Коробов С.А.