Обработка массивов.
При обработке массивов обычно используются косвенные режимы адресации.
Примечание: строку символов тоже можно рассматривать как символьный массив.
При косвенной адресации в качестве адреса используется базовый (ВХ или ВР) или индексный (SI или DI) регистр, содержащий смещение в сегменте данных. Адрес операнда загружается в регистр командой LEA либо командой MOV с использованием операции OFFSET.
mas dw 0,2,-3,4,-15 ;определение массива
lea si,mas ;адрес массива загружаем в si
mov ax,[si] ;первый элемент массива передается в ах
add si,2 ;переходим ко второму элементу массива
mov bx,[si] ;второй элемент массива передается в bx
Ниже приведен пример обработки числового массива – нахождение произведения всех его элементов (слов) – с использованием косвенной адресации.
sseg segment stack
dw 32 dup (?)
sseg ends
dseg segment
a dw 5,1,1,1,2,3,-1 ;определение массива
n dw 7 ;число элементов массива
p dw ? ;переменная для произведения
dseg ends
cseg segment
assume ds:dseg, cs:cseg,ss:sseg
extrn writer:near
start proc far ;процедура инициализации сегментного регистра ds
push ds
mov ax,0
push ax
mov ax,dseg
mov ds,ax
call main ;вызов главной процедуры
ret
start endp
main proc near ;главная процедура
mov cx,n ;в сх – число элементов массива
dec cx ;уменьшаем его на 1
lea si,a ;в si – адрес массива
mov ax,[si] ;в ах – первый элемент массива
mov p,ax ;сначала произведение равно первому элементу массива
cycle:inc si ;сдвигаемся к следующему элементу массива (если бы был
Inc si ;определен массив байтов, то была бы одна команда inc)
mov ax,[si] ;в ах – следующий элемент массива
mul p ;умножаем его на произведение, результат – в ах
mov p,ax ;и передаем в переменную р
loop cycle ;повторяем
mov ax,p ;произведение передаем в ах
call writer ;и выводим на экран
ret
main endp
cseg ends
end start
При базовой адресации в качестве адреса используются две составляющие: базовый (ВХ или ВР) регистр и смещение в команде. Смещение операнда равно сумме составляющих.
mas dw 0,2,-3,4,-15 ;определение массива
lea bx,mas ;адрес массива загружаем в bx
mov ax,6[bx] ;обе команды идентичны: складываем смещение,
mov аx,[bx+6] ;находящееся в bx, с 6, а затем берем данные
;в сегменте данных по этому смещению и засылаем
;в ах (4-й элемент массива)
При индексной адресации в качестве адреса используются две составляющие: переменная, определяющая имя массива, и индекс, задающий позицию элемента в массиве.
mas db 'Символьный массив' ;определение массива
mov si,3 ;загружаем в si индекс элемента массива
mov аx,mas[si] ;четвертый элемент массива (буква в)
;передается в аx
Ниже приведен пример обработки числового массива – нахождение произведения всех его элементов (слов) – с использованием индексной адресации.
sseg segment stack
dw 32 dup (?)
sseg ends
dseg segment
a dw 5,1,4,1,2,3,-1 ;определение массива
n dw 7 ;число элементов массива
p dw ? ;переменная для произведения
dseg ends
cseg segment
assume ds:dseg, cs:cseg,ss:sseg
extrn writer:near
start proc far ;процедура инициализации сегментного регистра ds
push ds
mov ax,0
push ax
mov ax,dseg
mov ds,ax
call main ;вызов главной процедуры
ret
start endp
main proc near ;главная процедура
mov cx,n ;в сх – число элементов массива
dec cx ;уменьшаем его на 1
mov si,0 ;в si – индекс первого элемента массива
mov ax,a[si] ;в ах – первый элемент массива
mov p,ax ;сначала произведение равно первому элементу массива
cycle:inc si ;сдвигаемся к следующему элементу массива
inc si
mov ax,a[si] ;в ах – следующий элемент массива
mul p ;умножаем его на произведение, результат – в ах
mov p,ax ;и передаем в переменную р
loop cycle ;повторяем
mov ax,p ;произведение передаем в ах
call writer ;и выводим на экран
ret
main endp
cseg ends
end start
При базово-индексной адресации в качестве адреса используются две составляющие: базовый регистр и индексный регистр. Смещение операнда равно сумме составляющих.
mas dw 0,2,-3,4,-15 ;определение массива
lea bx,mas ;адрес массива загружаем в bx
mov si,4 ;смещение загружаем в si
mov ax,[bx+si] ;обе команды идентичны: складываем смещение,
mov аx,[bx][si] ;находящееся в bx, со смещением из si
;а затем берем данные в сегменте данных
;по этому смещению и засылаем в ах
;(3-й элемент массива)
Ниже приведен пример обработки числового массива – нахождение произведения всех его элементов (слов) – с использованием базово-индексной адресации.
sseg segment stack
dw 32 dup (?)
sseg ends
dseg segment
a dw 5,-7,4,1,2,3,-1 ;определение массива
n dw 7 ;число элементов массива
p dw ? ;переменная для произведения
dseg ends
cseg segment
assume ds:dseg, cs:cseg,ss:sseg
extrn writer:near
start proc far ;процедура инициализации сегментного регистра ds
push ds
mov ax,0
push ax
mov ax,dseg
mov ds,ax
call main ;вызов главной процедуры
ret
start endp
main proc near ;главная процедура
mov cx,n ;в сх – число элементов массива
dec cx ;уменьшаем его на 1
lea bx,a ;в bx – адрес массива
mov si,0 ;в si – индекс первого элемента массива
mov ax,[bx][si] ;в ах – первый элемент массива
mov p,ax ;сначала произведение равно первому элементу массива
cycle:inc si ;сдвигаемся к следующему элементу массива
inc si
mov ax,[bx][si] ;в ах – следующий элемент массива
mul p ;умножаем его на произведение, результат – в ах
mov p,ax ;и передаем в переменную р
loop cycle ;повторяем
mov ax,p ;произведение передаем в ах
call writer ;и выводим на экран
ret
main endp
cseg ends
end start
При базово-индексной адресации со смещением в качестве адреса используются три составляющие: базовый регистр, индексный регистр и смещение в команде. Смещение операнда равно сумме составляющих.
mas dw 0,2,-3,4,-15 ;определение массива
lea bx,mas ;адрес массива загружаем в bx
mov di,4 ;смещение загружаем в si
mov ax,[bx+2+di] ;все команды идентичны: складываем смещение,
mov ax,[di+bx+2] ;находящееся в bx, со смещением из di и плюс 2,
mov ax,[bx+2][di] ;а затем берем данные в сегменте данных
mov аx,[bx][di+2] ;по этому смещению и засылаем в ах
;(3-й элемент массива)
Этот вид адресации можно использовать для работы с таблицами как с двумерными массивами. Например, базовый регистр содержит начальный адрес массива, а значение смещения индексного регистра – смещение по строке и столбцу.
Ниже приведен пример формирования единичной матрицы A порядка N (это матрица, у которой вдоль главной диагонали стоят единицы, а остальные элементы - нули) и использованием базово-индексной адресации со смещением.
Индексы i и j хранятся в регистрах DI и SI соответственно. Элемент матрицы в программе имеет вид A[bx][si]. Для перехода к новой строке содержимое регистра ВХ, сначала нулевое, увеличивается каждый раз на N (каждый элемент матрицы занимает в памяти 1 байт). Для вывода результата в виде квадратной матрицы используется процедура WRITERN (легкая модификация процедуры WRITER), которая после вывода очередного числа не переводит курсор на новую строку – это делает процедура PSBK, вызываемая после вывода на экран очередной строки матрицы.
sseg segment stack
dw 32 dup (?)
sseg ends
dseg segment
n = 5
a db n*n dup (?) ;определение двумерного массива
dseg ends
cseg segment
assume ds:dseg, cs:cseg,ss:sseg
extrn writern:near,psbk:near
start:mov ax,dseg
mov ds,ax
mov ch,n ;количество строк (внешний цикл организован
;по количеству строк)
mov bx,0 ;
mov di,0 ;i=0
z1: mov si,0 ;j=0
mov cl,n ;количество столбцов (внутренний цикл организован
;по количеству столбцов
z2: cmp di,si ;i=j?
jne neq ;не равно, идем на метку neq
mov a[bx][si],1 ;иначе засылаем на место элемента 1
jmp cont ;идем на метку cont
neq: mov a[bx][si],0 ;засылаем на место элемента 0
cont: mov al,a[bx][si];готовим элемент к выводу на экран
mov ah,0
call writern ;выводим его
inc si ;j=j+1
dec cl ;уменьшаем количество столбцов на 1
jnz z2 ;если еще есть столбцы, продолжаем - идем на метку z2
call psbk ;переводим курсор на следующую строку
inc di ;i=i+1
add bl,n
dec ch ;уменьшаем количество строк на 1
jnz z1 ;если еще есть строки, продолжаем - идем на метку z2
mov ax,4c00h ;завершение программы
int 21h
cseg ends
end start