Обработка строк.
- В мнемонике команд обработки строк всегда содержится буква S (String — строка).
Она является последней или предпоследней буквой.
- Содержимое строки для микропроцессора НЕ имеет никакого значения. Это могут быть
символы, числа и все, что угодно. Основное, что имеет значение, — это длина операнда.
- Строка в базовом Ассемблере может обрабатываться побайтно (BYTE —
последняя буква в команде будет В) или пословно (WORD
— последняя буква в команде будет W).
- Строка может обрабатываться группой (цепочкой), тогда перед командой
появляется префикс REPx (REPeat — повторить). Количество повторений должно
находиться в регистре СХ. Этот префикс алгоритмически подобен команде LOOPx.
- Строка-приемник должна находиться обязательно в дополнительном сегменте памяти ES
со смещением DI (адресация < ES:DI > ).
- Строка-источник должна находиться в сегменте данных DS со смещением SI
(адресация < DS:SI > ). Допускается замена регистра сегмента DS с помощью префикса
замены сегмента.
- В процессе циклического выполнения команд указатели SI и DI автоматически
модифицируются в зависимости от длины элемента строки и значения флага направления DF:
- Если < DF >=0, значения SI и DI увеличиваются (строка обрабатывается
слева направо — в сторону больших адресов).
- Если < DF >=1, значения SI и DI уменьшаются (строка обрабатывается
справа налево — в сторону меньших адресов).
- Флаг направления DF очищается или устанавливается, соответственно, командами
CLD
или STD
.
- Длина строки в базовом Ассемблере <= 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