Пример использования команд усл. перехода, сравнения и циклов
Дана матрица целых байтовых величин, размером 4*5, необходимо подсчитать количество нулей и заменить их числом 0FFh. Под стек отведем 256 байтов, программу оформим как две последовательные процедуры: внешняя (FAR)– это связь с ОС, внутренняя (NEAR) – решение поставленной задачи. 1. ; prim.asm 2. title prim.asm 3. page , 132 4. Sseg segment para stack ‘stack’ 5. db 256 dup (?) 6. Sseg ends 7. Dseg segment para public ‘data’ 8. Dan db 0,2,5,0,91 ; адрес первого элемента массива 9. db 4,0,0,15,47 ; имя - Dan 10. db 24,15,0,9,55 11. db 1,7,12,0,4 12. Dseg ends 15. Cseg segment para public ‘code’ 16. Assume cs: cseg, ds:dseg, ss:sseg 17. start proc far 18. push DS ; для связи 19. push AX ; с ОС 20. mov BX, Dseg ; загрузка адреса сегмента данных 21. mov DS, BX ; в регистр DS 22. call main 23. ret 24. start endp 25. main proc near 26. mov BX, offset Dan 27. mov CX, 4 ; количество повторений внешнего цикла 28. nz1: push CX 29. mov DL, 0 ; счетчик нулей в строке матрицы 30. mov SI, 0 31. mov CX, 5 ; количество повторений внутреннего цикла 32. nz2: push CX 33. cmp byte ptr [BX+SI], 0 34. jne mz 35. mov byte ptr [BX+SI], 0FFh 36. inc DL 37. mz: inc SI 38. pop CX 39. kz2: loop nz2 40. add DL, ‘0’ ; вывод на экран 41. mov AH, 6 ; количества нулей 42. int 21h 43. add BX, 5 ; переход к следующей строке матрицы 44. pop CX 45. kz1: loop nz1 46. ret 47. main endp 48. Sseg ends 49. end start Задача решена с помощью двух вложенных циклов, во внутреннем осуществляется просмотр элементов текущей строки (32-39), увеличение счетчика нулей и пересылка константы 0FFh в байт, содержащий ноль. Во внешнем цикле осуществляется переход к следующей строке очисткой регистра SI (строка 30 ) и увеличением регистра BX на количество элементов в строке (40). Физически последняя команда программы (49) в качестве параметра указывает метку команды, с которой необходимо начинать выполнение программы. Директива title задает заголовок каждой странице листинга, заголовок может содержать до 60 символов. Директива page устанавливает количество строк на странице листинга – 1-й параметр (здесь он отсутствует, значит берется значение по умолчанию 57) и количество символов в каждой строке ( здесь 132, возможно от 60 до 132, по умолчанию – 80). Pageбезпараметров осуществляет перевод печати на новую страницу и увеличение на 1 номера страницы листинга. Эти директивы могут отсутствовать.
30) Работа с массивами в Ассемблере, примеры. Массивы в языке Ассемблер описываются директивами определения данных, возможно с использование конструкции повторения DUP. Например, x DW 30 dup ( ? ) Так можно описать массив x, состоящий из 30 элементов длиной в слово, но в этом описании не указано как нумеруются элементы массива, т.е. это может быть x[0..29] и x[1..30] и x[k..29+k]. Если в задаче жестко не оговорена нумерация элементов, то в Ассемблере удобнее считать элементыот нуля, тогда адрес любого элемента будет записываться наиболее просто: адрес (x[i]) = x + (type x) * i В общем виде, когда первый элемент имеет номер k , для одномерного массива будет: адрес (x[i]) = x + (type x) * (i – k) Для двумерного массива - A[0..n-1, 0..m-1]адрес (i,j) – го элемента можно вычислить так: адрес (A[i,j]) = A + m * (type A) * i + (type A) *j С учетом этих формул для записи адреса элемента массива можно использовать различные способы адресации. Для описанного выше массива слов, адрес его i-го элемента равен: x + 2*i = x + type (x) * i, Т.е. адрес состоит из двух частей: постоянной x и переменной 2 * i, зависящей от номера элемента массива. Логично использовать адресацию прямую с индексированием: x – смещение адреса относительно начала, а 2*i – в регистре модификаторе SI или DI x[ i ] Для двумерного массива, например: A DD n DUP (m Dup (?) ) ; A[0..n - 1, 0..m - 1] получим адрес (A[ i,j ]) = A + m * 4 * i + 4 *j, Т.е. имеем в адресе постоянную часть А и две переменных m * 4 * iи 4 *j ,которые можно хранить в регистрах. Два модификатора есть в адресации по базе с индексированием, например: A[BX][DI]. Фрагмент программы, в которой в регистр AL записывается количество строк матрицы X DB 10 dup ( 20 dup (?) ), в которых начальный элемент повторяется хотя бы один раз. ---------------------------------- mov AL, 0 ; количество искомых строк mov CX, 10 ; количество повторений внешнего цикла mov BX, 0 ; начало строки 20*i m1: push CX mov AH, X[BX] ; 1-й элемент строки в AH mov CX, 19 ; количество повторений внутреннего цикла mov DI, 0 ; номер элемента в строке ( j ) m2: inc DI ; j = j + 1 cmp AH, X[BX][DI] ; A[i,0] = A[i,j] loopne m2 ; первый не повторился? Переход на m2 jne L ; не было в строке равных первому? Переход на L inc AL ; первый повторился, увеличиваем счетчик строк L: pop CX ; восстанавливаем CX для внешнего цикла add BX, 20 ; в BX начало следующей строки loop m1 ------------------------------
12) Команды побитовой обработки данных: логические операции, операции сдвига. К командам побитовой обработки данных относятся логические команды, команды сдвига, установки, сброса и инверсии битов. Логические команды: and, or, xor, not. Для всех логических команд, кроме not, операнды одновременно не могут находиться в памяти, OF = CF = 0, AF – не определен, SF, ZF, PF определяются результатом команды. and OP1, OP2; (OP1) логически умножается на (OP2), результат OP1 Пример: (AL) = 1011 0011, (DL) = 0000 1111, and AL, DL; (AL) = 0000 0011 Второй операнд называют маской. Основным назначением команды and является установка в ноль с помощью маски некоторых разрядов первого операнда. Нулевые разряды маски обнуляют соответствующие разряды первого операнда, а единичные оставляют соответствующие разряды первого операнда без изменения. Маску можно задавать непосредственно в команде и можно извлекать из регистра или памяти. Например: 1) and CX, 0FFh ; маской является константа 2) and AX, CX ; маска содержится в регистре 3) and AX, TOT ; маска в ОП по адресу (DS) + TOT 4) and CX, TOT[BX+SI] ; …в ОП по адресу (DS) + (BX) + (SI) + TOT 5) and TOT[BX+SI], CX ; в ноль устанавливаются некоторые разряды ОП 6) and CL, 0Fh ; в ноль устанавливаются старшие 4 разряда регистра CL Команда – or OP1, OP2; результатом является логическое сложение 1-ого со 2-ым и результат по адресу первого.0 – если оба нули. Эта команда используется для установки в 1 заданных битов 1-го операнда с помощью маски OP2. … Например: (AL) = 1011 0011, (DL) = 0000 1111 or AL, DL; (AL) = 1011 1111 …… В команде могут использоваться различные операнды: or CX, 00FFh ; or TAM, AL ; or TAM[BX][DX], CX Если во всех битах результата будет 0, то ZF = 1. Команда xor OP1, OP2; 1 xor 1 = 0, 0 xor 0 = 0, в ост. сл. = 1 Например: (AL) = 1011 0011, маска = 000 01111 xor AL, 0Fh; (AL) = 1011 1100 Команда not OP; результат – инверсия значения операнда Если (AL) = 0000 0000, not AL; (AL) = 1111 1111 Значения флагов не изменяются. Примеры. 1) xor AX, AX ; обнуляет регистр AX быстрее, чем mov и sub 2) xor AX, BX; меняет местами значения AX и BX xor BX, AX ; быстрее, чем команда xor AX, BX; xchg AX, BX 3) Определить количество задолжников в группе из 20 студентов. Информация о студентах содержится в массиве байтов X DB 20 DUP (?), причем в младших 4 битах каждого байта содержатся оценки, т.е. 1 – сдал экзамен, 0 – «хвост». В DL сохраним количество задолжников. ----------------------------- mov DL, 0 mov SI, 0 ; i = 0 mov CX, 20 ; количество повторений цикла nz: mov AL, X[SI] and AL, 0Fh ; обнуляем старшую часть байта xor AL, 0Fh ; jz m ; ZF = 1, хвостов нет, передаем на повторение цикла inc DL ; увеличиваем количество задолжников m: inc SI ;переходим к следующему студенту loop nz add DL, “0” mov AH, 6 int 21h -------------------------- Команды сдвига. Формат команд арифметического и логического сдвига можно представить так: sXY OP1, OP2 ; <комментарий> Здесь X - h или a, Y – l или r; OP1 – r (регистр) или m (память), OP2 – d (непоср) или CL. ХУ определяет тип и направление. И для всех команд сдвига в CL используются только 5 младших разрядов, принимающих значения от 0 до 31. При сдвиге на один разряд:
Здесь знаковый бит распространяется на сдвигаемые разряды. Например, (AL) = 1101 0101 sar AL, 1 ; (AL) = 1110 1010 и CF = 1 Сдвиги больше, чем на 1,эквивалентны соответствующим сдвигам на 1, выполненным последовательно. Сдвиги повышенной точности для i186 и выше: shrd OP1, OP2, OP3 ; shld OP1, OP2, OP3 ; Содержимое первого операнда (OP1) сдвигается на (OP3) разрядов также, как и в командах shr и shl но бит, вышедший за разрядную сетку, не обнуляется, а заполняется содержимым второго операнда, которым может быть только регистр. Циклические сдвиги:
После выполнения команды циклического сдвига CF всегда равен последнему биту, вышедшему за пределы приемника. Циклические сдвиги с переносом содержимого Флажка CF:
Для всех команд сдвига флаги ZF, SF, PF устанавливаются в соответствии с результатом. AF – не определен. OF – не определен при сдвигах на несколько разрядов, при сдвиге на 1 разряд в зависимости от команды: - для циклических команд, повышенной точности и sal , shl флаг OF = 1, если после сдвига старший бит изменился; - после sar OF = 0; - после shr OF = значению старшего бита исходного числа. BT <приемник>, <источник>
4) Структуры в Ассемблере, их описание и использование. Структура состоит из полей-данных различного типа и длины, занимая последовательные байты памяти. Чтобы использовать переменные типа структура, необходимо вначале описать тип структуры, а затем описать переменные такого типа. Описание типа структуры: <имя типа> struc <описание поля> ------------------------ <описание поля> <имя типа> ends <имя типа> - это идентификатор типа структуры, struc и ends - директивы, причем <имя типа > в директиве ends также обязательно. Для описания полей используются директивы определения данных и памяти: DB, DW, DD.Имя, указанное в этих директивах, является именем поля, но имена полей не локализованы внутри структуры, т.е. они должны быть уникальными в рамках всей программы, кроме того, поля не могут быть структурами – не допускаются вложенные структуры. Например TData struc ; TData – идентификатор типа y DW 2000 ; y, m, d – имена полей. Значения, указанные m DB ? ; в поле операндов директив DW и DB , d DB 28 ; называются значениями полей, принятыми TData ends ; по умолчанию. ? – означает, что значения по умолчанию нет. На основании описания типа в программу ничего не записывается и память не выделяется. Описание типа может располагаться в любом месте программы, но только до описания переменных данного типа. На основании описания переменных Ассемблером выделяется память в соответствии с описанием типа в последовательных ячейках, так что в нашем случае размещение полей можно представить так: 2б 1б 1б размеры полей в байтах TData y m d
+0 +2 +3 смещение относительно начала структуры. Описание переменных типа структуры осуществляется с помощью директивы вида: имя переменной имя типа <нач. значения> Здесь уголки не метасимволы, а реальные символы языка, внутри которых через запятую указываются начальные значения полей. Нач-ым значением может быть: 1) ? 2) выражение 3) строка 4) пусто. Например: y m d dt1 TData <?, 6, 4> ? 6 4 dt2 TData <1999, , > 1999 ? 28 dt3 TData < , , > 2000 ? 28 Идентификатор типа TData используется как директива для описания переменных также, как используются стандартные директивы DB, DW и т.д. Если начальные значения не будут умещаться в отведенное ему при описании типа поле, то будет фиксироваться ошибка. Правила использования начальных значений и значений по умолчанию: - приоритетными являются начальные значения полей, - при описании переменных, т.е. если при описании переменной для поля указан ? или какое-либо значение, то значения этих полей по умолчанию игнорируются. Правила использования начальных значений и значений по умолчанию: 1) если в поле переменной указан знак ?, то это поле не имеет начального значения, даже если это поле имеет значение по умолчанию (поле y переменной dt1); 2) Если в поле переменной указано выражение или строка, то значение этого выражения или сама строка становится начальным значением этого поля (поля m и d переменной dt1 и поле y переменной dt2); 3) Если начальное значение поля переменной «пусто» - ничего не указано при описании переменной, то в качестве начального устанавливается значение по умолчанию – значение, указанное при описании типа, если же в этом поле при описании типа стоит знак ?, то данное поле не имеет никакого начального значения (поля m переменных dt2 и dt3). Значения по умолчанию устанавливаются для тех полей, которые являются одинаковыми для нескольких переменных одного типа, например, год поступления на факультет одинаков для группы студентов. Любая переменная может изменять свое значение в процессе выполнения программы и поэтому структура может не иметь как значений по умолчанию, так и начальных значений. Отсутствие начального значения отмечается запятой. Если отсутствуют начальные значения нескольких последних полей, то запятые можно не ставить. Если отсутствуют значения первого поля или полей, расположенных в середине списка полей, то запятые опускать нельзя. Например: dt4 TData <1980, ,> можно dt4 TData <1980> dt5 TData <, , 5> нельзя заменить на dt5 TData < 5 >. Если отсутствуют все начальные значения, опускаются все запятые, но угловые скобки сохраняются: dt6 TData < > При описании переменных, каждая переменная описывается отдельной переменной, но можно описать массив структур, для этого в директиве описания переменной указывается несколько операндов и (или) конструкция повторения DUP. Например: dst TData <, 4, 1>, 25 DUP (< >) Описан массив из 26 элементов типа TData, и первый элемент (первая структура) будет иметь начальные значения 2000, 4, 1, а все остальные 25 в качестве начальных будут иметь значения, принятые по умолчанию: 2000, ?, 28. Имя первой структуры dst, второй – dst+4, третьей – dst+8 и т.д. Работать с полями структуры можно также, как с полями переменной комбинированного типа в языках высокого уровня: <имя переменной > . < имя поля> Например, dt1.y, dt2.m, dt3.d Ассемблер приписывает имени типа и имени переменной размер (тип), равный количеству байтов, занимаемых структурой type TData = type dt1 = 4 И это можно использовать при программировании, например, так: ; выполнить побайтовую пересылку dt1 в dt2 mov CX, type TData ; количество повторений в CX mov SI, 0 ; i = 0 m: mov AL, byte ptr dt1[SI] ; побайтовая пересылка mov byte ptr dt2[SI], AL ; dt1 в dt2 inc SI ; i = i+1 loop m ; использование byte ptr обязательно т.к. операторы разного типа ----------------------------------- Точка, указанная при обращении к полю, это оператор Ассемблера, который вычисляет адрес по формуле: <адресное выражение> + <смещение поля в структуре> Тип полученного адреса совпадает с типом поля, т.е. type (dt1.m) = type m = byte Адресное выражение может быть любой сложности, например: 1) mov AX, (dts+8).y 2) mov SI, 8 inc (dts[SI]).m ; Aисп = (dts + [SI]). m = (dts + 8).m 3) lea BX, dt1 mov [BX].d, 10 ; Aисп = [BX] + d = dt1.d Замечания: 1) type (dts[SI]).m = type (dts[SI].m) = 1, но type dts[SI].m = type dts = 4 2) Если при описании типа структуры в директиве, описывающей некоторое поле, содержится несколько операндов или конструкция повторения, то при описании переменной этого типа данное поле не может иметь начального значения и не может быть определено знаком ?, это поле должно быть пустым. Одно исключение: если поле описано как строка, то оно может иметь начальным значением строку той же длины или меньшей, Например: student struc f DB 10 DUP (?) ; фамилия i DB “ ******* “ ; имя gr DW ? ; группа oz DB 5, 5, 5 ; оценки student ends Описание переменных: st1 student <“Petrov”, > ; нельзя, т.к. поле f не строка st2 student < , “Petr”, 112, > ; можно, f – не имеет начального ; значения st3 student < , “Aleksandra” > ; нельзя, в i 10 символов, а допустимо не больше 7. Примеры программ с использованием данных типа структура. ; prim1.asm – прямое обращение к полям структуры .model tiny .code org 100h ; обход 256 байтного префикса пр-го сегмента – PSP… Start: mov AH, 9 mov DX, offset message int 21h ; lea DX, st1.s int 21h lea DX, st1.f int 21h lea DX, st1.i int 21h ret ; message DB “ hello”, 0dh, 0ah, ”$” tst struc ; описание типа структуры s DB “student”,”$” f DB “Ivanov “,”$” i DB “Ivan “,”$” tst ends st1 tst < > ; описание переменной типа tst end start org 100h - все сегментные регистры вначале выполнения программы содержат адрес блока PSP, который резервируется непосредственно перед EXE и COM файлами. Смещением для 1-ой команды программы является адрес 100h. Переход на первую выполняемую команду и происходит с помощью директивы ORG 100h. Prim2.asm – обращение к полям структуры в цикле Model tiny Code org 100h ; обход 256 байтного префикса пр-го сегмента – PSP… Start: mov AH, 9
Популярное: Как построить свою речь (словесное оформление):
При подготовке публичного выступления перед оратором возникает вопрос, как лучше словесно оформить свою... Модели организации как закрытой, открытой, частично открытой системы: Закрытая система имеет жесткие фиксированные границы, ее действия относительно независимы... Почему стероиды повышают давление?: Основных причин три... Почему двоичная система счисления так распространена?: Каждая цифра должна быть как-то представлена на физическом носителе... ©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (666)
|
Почему 1285321 студент выбрали МегаОбучалку... Система поиска информации Мобильная версия сайта Удобная навигация Нет шокирующей рекламы |