Информатика_лек8.ppt
- Количество слайдов: 17
Лекция 8 Массивы в программе на ассемблере Из 17 1
Описание массивов • Массивы в Ассемблере описываются при помощи директив определения с использованием конструкции повторения DUP. Например, DW 30 DUP(? ) Т. е. при описании указывается количество элементов и их тип, НО не указывается как нумеруются (индексируются) его элементы: начиная с 0 или 1 или с др. числа. Лучше нумеровать с 0, т. к. в этом случае становится простой адресация – адрес очередного элемента в памяти равен его номеру (+адрес первого элемента массива). • Аналогично описываются и двумерные массивы. Например, массив A, состоящий из N строк и M столбцов опишется так: A DD N DUP (M DUP(? )) Из 17 2
Модификация адресов • Ранее указывали точные адреса для операндов из памяти: MOV CX, A • Но можно вместе с адресом указать регистр: MOV CX, A[BX] Тогда команда будет работать не с указанным в ней адресом A, а с так называемым исполнительным адресом Aисп = (A+[BX]) mod 216 Здесь [BX] обозначает содержимое регистра BX. Иначе говоря, прежде чем выполнить команду, процессор прибавит к адресу A, указанному в команде, текущее значение регистра BX, получит новый адрес и именно из ячейки с этим адресом возьмет второй операнд. Если в результате сложения получится слишком большая сумма, то от нее берется только последние 16 битов, на что и указывает операция mod в приведенной формуле. Из 17 3
Регистры-модификаторы • Замена адреса из команды на исполни-тельный адрес называется модификацией адреса, а регистр, участвующий в моди-фикации, принято называть регистром-модификатором. В качестве модификатора может выступать не любой регистр, а только один из следующих четырех: BX, BP, SI и DI. • Модификация адресов потребуется, например, при работе с индексами массивов. Из 17 4
Пример, стр. 1 Пример. Пусть имеется массив X DW 100 DUP (? ) (т. е. имеется массив X[0. . 99] ). Требуется записать в регистр AX сумму его элементов. • Для нахождения суммы, как ясно, нужно сначала в AX записать 0, а затем в цикле выполнять операцию AX: =AX+X[i] при i от 0 до 99. Поскольку адрес элемента X[I] равен X+2*I , то команда, соответствующая данной операции должна быть следующей: ADD AX, X+2*I • Но такая команда запрещена – вторая ее часть (адрес) меняется. Чтобы разрешить эту проблему и используется модификация адресов. В данном случае будем заносить переменное слагаемое (2*I) в регистр SI и команда перепишется в виде: ADD AX, X[SI] • Чтобы правильно менять содержимое регистра SI, нужно сначала в SI занести 0, а затем увеличивать его значение с шагом 2. В результате наша команда будет работать с адресами X, X+2, x+4, … X+198 (напомним, что массив двумерный и общее число элементов равно 200). Из 17 5
Пример, стр. 2 • Поскольку в данном случае регистр-модификатор используется для хранения индекса, то такой регистр называют индексным, а описанный способ получения адреса переменной с индексом – индексированием. • В итоге фрагмент программы нахождения суммы элементов массива X имеет вид: MOV AX, 0 ; начальное значение суммы MOV CX, 100 ; счетчик цикла MOV SI, 0 ; начальное значение (удв-го) индекса L: ADD AX, X[SI] ; AX: =AX+X[I] ADD SI, 2 ; следующий индекс LOOP L ; цикл 100 раз Из 17 6
; вычисление суммы элементов массива из 10 элементов ; результат см. в EBX. 386. model flat, stdcall includelib kernel 32. lib Exit. Process proto : DWORD. data X DWORD 1, 2, 3, 4, 5, 6, 7, 8, 9, 10. code start: MOV EAX, 0 ; начальное значение суммы MOV ECX, 10 ; счетчик цикла MOV ESI, 0 ; нач. значение (учетверенного) индекса L: ADD EAX, X[SI] ; EAX: =EAX+X[I] ADD ESI, 4 ; следующий индекс LOOP L ; цикл 10 раз MOV EBX, EAX ; сохраняем результат в EBX invoke Exit. Process, 0 end start Из 17 7
Модификация по нескольким регистрам • В ПК разрешено указывать сразу два модификатора, причем один из них обязательно должен быть BX или BP, а другой – регистром SI или DI (модифицировать по парам BX и BP или SI и DI нельзя). Применим это на примере. • Пример. Пусть имеется матрица (двумерный массив) размером 10 х20: A DB 10 DUP (20 DUP(? )) (т. е A[0. . 9, 0. . 19] ) Требуется записать в регистр AL количество таких строк этой матрицы, в которых начальный элемент строки встречается еще раз. Из 17 8
Решение примера, стр. 1 • При расположении элементов матрицы в памяти по строкам (первые 20 байтов – начальная строка матрицы, следующие 20 байтов – вторая строка и т. д. ) адрес элемента A[i, j] равен A+20*i+j. • Для хранения величины 20*i отведем регистр BX, а для хранения j – регистр SI. Тогда A[BX] – это начальный адрес I-й строки матрицы, а A[BX][SI] - адрес j-го элемента этой строки. Из 17 9
Решение примера, стр 2 MOV AL, 0 ; количество искомых строк ; внешний цикл по строкам MOV CX, 10 ; счетчик внешнего цикла MOV BX, 0; смещение от А до начала ; строки (20*I) L: MOV AH, A[BX] ; AH – нач. элемент строки MOV DX, CX ; запоминание CX внешнего цикла Из 17 10
Решение примера, стр 3 ; внутренний цикл по столбцам MOV CX, 19 ; задание счетчика внутр. цикла MOV SI, 0 ; индекс элемента внутри строки (j) L 1: INC SI ; j: =j+1 CMP A[BX][SI], AH ; A[i, j] =AH ? LOOPNE L 1 ; цикл, пока A[I, j]<>AH, но не более 19 раз JNE L 2 ; AH не повторился –> L 2 INC AL ; учет строки ; конец внутреннего цикла Из 17 11
Решение примера, стр 4 L 2: MOV CX, DX ; восстановить CX для внешнего цикла ADD BX, 20; на начало следующей строки LOOP L ; цикл 10 раз Здесь дополнительно использован вариант команды цикла LOOPNE, которая осуществит выход из цикла не только при равенстве вышесравниваемых значений, но и при счетчике (CX) равном нулю. Из 17 12
Из 17 13
Загрузка адресов Выше мы активно пользовались регистрами, в которых размещены нужные адреса. Но как их туда занести? Для занесения адреса в регистр служит команда LEA op 1, op 2 Эта команда вычисляет исполнительный адрес второго операнда и записывает его в регистр, указанный первым операндом. Отметим, что данная команда похожа на команду MOV, но у них имеется принципиальное различие: если LEA записывает в регистр сам адрес, указанный в команде, то MOV записывает содержимое ячейки с указанным адресом. Из 17 14
Пример с загрузкой адресов Пусть в программе имеются описания: Q DW 45 R DW – 8 (т. е. отметим, что адрес R на 2 больше, чем адрес Q) Тогда LEA BX, Q ; BX: = адрес Q MOV BX, Q ; BX: =содержимое Q Если в качестве второго операнда указан модифицированный адрес, то сначала вычисляется исполнительный адрес и лишь затем производится загрузка в регистр: MOV SI, 2 LEA AX, Q[SI] ; AX: =Aисп=Q+[SI] = адрес(Q+2)=адрес (R) Из 17 15
Команда перекодировки При работе с модификацией адресов используется и команда перекодировки XLAT Действие этой команды заключается в том, что содержимое байта памяти, адрес которого равен сумме текущих значений регистров BX и AL, записывается в регистр AL: =байт по адресу [BX+AL] Посмотрим, как эта команда действительно может быть применена для перекодировки символов. Из 17 16
Пример с перекодировкой Пример. Преобразовать любую 16 -ричную цифру-число (от 0 до 15) в цифру-символ. Для этого определим в программе таблицу DIG 16, перечислив в ней все символы, изображающие 16 ричные цифры: DIG 16 DB ‘ 0123456789 ABCDEF’ ; DIG 16[0. . 15] Пусть в регистре AL находится число от 0 до 15 (скажем, 14). Тогда записать в этот регистр соответствующий символ-цифру (“E”) можно так: LEA BX, DIG 16 ; BX – на начало DIG 16 XLAT ; AL: =DIG 16[AL] Из 17 17
Информатика_лек8.ppt