Assume cs: cseg, ds:dseg, ss:sseg
Start proc far Push DS ; для связи Push AX ; с ОС 18. movBX, Dseg ;загрузка адреса сегмента данных 19. movDS, BX ;в регистр DS Call main Ret Start endp Main proc near Mov BX, offset Dan 25. movCX, 4 ;количество повторений внешнего цикла Nz1: push CX 27. movDL, 0 ;счетчик нулей в строке матрицы Mov SI, 0 29. movCX, 5 ;количество повторений внутреннего цикла Nz2: push CX 31. cmp byte ptr [BX+SI], 0 Jnemz 33. movbyteptr [BX+SI], 0FFh ; увеличили на единичку Inc DL Mz: inc SI Pop CX Kz2: loop nz2 38. addDL, ‘0’ ;вывод на экран 39. mov AH, 6 ;количества нулей Int 21h 41. addBX, 5 ;переход к следующей строке матрицы Pop CX Kz1: loop nz1 Ret Main endp Cseg ends End start Задача решена с помощью двух вложенных циклов, во внутреннем осуществляется просмотр элементов текущей строки (32-39), увеличение счетчика нулей и пересылка константы 0FFh в байт, содержащий ноль. Во внешнем цикле осуществляется переход к следующей строке очисткой регистра SI (строка 30 ) и увеличением регистра BX на количество элементов в строке (40). Физически последняя команда программы (49) в качестве параметра указывает метку команды, с которой необходимо начинать выполнение программы. Директива title задает заголовок каждой странице листинга, заголовок может содержать до 60 символов. Директива page устанавливает количество строк на странице листинга – 1-й параметр (здесь он отсутствует, значит, берется значение по умолчанию 57) и количество символов в каждой строке (здесь 132, возможно от 60 до 132, по умолчанию – 80). Pageбезпараметров осуществляет перевод печати на новую страницу и увеличение на 1 номера страницы листинга.Эти директивы могут отсутствовать. Работа с массивами: Массивы в языке Ассемблер описываются директивами определения данных, возможно с использование конструкции повторения DUP. Например, xDW 30 dup ( ? ) Так можно описать массив x, состоящий из 30 элементов длиной в слово, но в этом описании не указано как нумеруются элементы массива, т.е. это может быть x[0..29] и x[1..30] и x[k..29+k]. Значит, в процессе программирования мы можем их нумеровать от любого числа: от Kдо K +1. Если в задаче жестко не оговорена нумерация элементов, то в Ассемблере удобнее считать элементыот нуля, тогда адрес любого элемента будет записываться наиболее просто: адрес (x[i]) = x + (type x) * i В общем виде, когда первый элемент имеет номер k , для одномерного массива будет: адрес (x[i]) = x + (typex) * (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 или DIx[ i ] Для двумерного массива, например: A DDnDUP (mDup (?) ); 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 записывается количество строк матрицы XDB 10 dup (20 dup (?) ), в которых первый элемент повторяется хотя бы один раз. ---------------------------------- movAL, 0; количество искомых строк movCX, 10 ;количество повторений внешнего цикла movBX, 0 ;начало строки 20*i M1: pushCX movAH, X[BX] ;1-й элемент строки в AH movCX, 19 ;количество повторений внутреннего цикла movDI, 0 ;номер элемента в строке ( j ) m2: inc DI; j = j + 1 cmp AH, X[BX][DI]; A[i,0] = A[i,j] loopnem2 ;первый не повторился? Переход на m2 jneL ;не было в строке равных первому? Переход на L incAL ;первый повторился, увеличиваем счетчик строк L: popCX; восстанавливаем CX для внешнего цикла addBX, 20 ;в BX начало следующей строки Loopm1 ------------------------------ Команды побитовой обработки данных: К командам побитовой обработки данных относятся логические команды, команды сдвига, установки, сброса и инверсии битов. Логические команды:and, or, xor, not. Для всех логических команд, кроме not, операнды одновременно не могут находиться в памяти, OF = CF = 0, AF – не определен, SF, ZF, PF определяются результатом команды. 1. andOP1, OP2; (OP1) логически умножается на (OP2), результат ®OP1 Пример: (AL) = 1011 0011, (DL) = 0000 1111, and AL, DL; (AL) = 0000 0011 Второй операнд называют маской. Основным назначением команды and является установка в ноль с помощью маски некоторых разрядов первого операнда. Нулевые разряды маски обнуляют соответствующие разряды первого операнда, а единичные оставляют соответствующие разряды первого операнда без изменения. Маску можно задавать непосредственно в команде и можно извлекать из регистра или памяти. Например: · andCX, 0FFh; маской является константа · andAX, CX; маска содержится в регистре СХ, а обнуляются какието разряды регистра АХ · andAX, TOT; маска в ОП по адресу (DS) (смещенное на 4 разряда влево)+ (значение переменной)TOT · andCX, TOT[BX+SI] ; маска лежит в ОП по адресу (DS) (смещенное на 4 разряда влево)+ (BX) + (SI) + TOT · andTOT[BX+SI], CX; маска находится в СХ, а обнуляются некоторые разряды в памяти · andCL, 0Fh; в ноль устанавливаются старшие 4 разряда регистра CL 2. Команда – orOP1, OP2;к содержимому первого операнда логически прибавляется содержимое второго операнда и результат посылается по адресу первого операнда. Второй операнд это тоже маска, которая используется для установки в единицу заданных разрядов первого операнда. Например: (AL) = 1011 0011; (DL) = 0000 1111; orAL, DL ; (AL) = 1011 1111 В команде могут использоваться различные операнды: or CX, 00FFh ; or TAM, AL ; or TAM[BX][DX], CX Если во всех битах результата будет 0, то ZF = 1. 3. Команда исключающее или - xorOP1, OP2; 1 xor 1 = 0, 0 xor 0 = 0, в ост.сл. = 1 Например: (AL) = 1011 0011, маска = 000 01111 xorAL, 0Fh; (AL) = 1011 1100 4. Команда notOP; результат – инверсия значения операнда Если (AL) = 0000 0000, not AL; (AL) = 1111 1111 Унарная команда notзначения флагов не изменяются. Примеры. 1) xorAX, AX ; обнуляет регистр AX быстрее, чем mov и sub 2) xorAX, BX; меняет местами значения AX и BX xorBX, AX ; быстрее, чем команда xor AX, BX; xchgAX, BX Пример: Определить количество задолжников в группе из 20 студентов. Информация о студентах содержится в массиве байтов XDB 20DUP (?), причем в младших 4 битах каждого байта содержатся оценки, т.е. 1 – сдал экзамен, 0 – «хвост». В DL сохраним количество задолжников. ----------------------------- Mov DL, 0 mov SI, 0 ; i = 0 movCX, 20 ;количество повторений цикла nz: movAL, X[SI] andAL, 0Fh ;обнуляем старшую часть байта xorAL, 0Fh ; jzm ;ZF = 1, хвостов нет, передаем на повторение цикла incDL; увеличиваем количество задолжников m: incSI;переходим к следующему студенту Loopnz add DL, “0” Mov AH, 6 Int 21h -------------------------- Команды сдвига: Формат команд арифметического и логического сдвига можно представить так: sXYOP1, OP2 ; <комментарий> Здесь X - H или A, Y – L или R; OP1 – R или M, OP2 – D или CL. И для всех команд сдвига в CL используются только 5 младших разрядов, принимающих значения от 0 до 31. При сдвиге на один разряд: - SHL - логическом сдвиге влево: при сдвиге на один разряд сдвигаемый разряд попадает во флажок CF, а на место сдвигаемого разряда ставится в ноль; - SHR -логический сдвиг вправо: сдвигаемый разряд заменяется нулем, а тот который выходит за пределы изменяет содержимое флага CF; - SAL – арифметический сдвиг влево:ничем не отличается от SHL - SAR – арифметический сдвиг вправо: отличается от SHR тем, что не нулем заполняется, а знаковым разрядом; Здесь знаковый бит распространяется на сдвигаемые разряды. Например, (AL) = 1101 0101 sarAL, 1 ; (AL) = 1110 1010 иCF = 1 Сдвиги повышенной точности для i186 и выше: shrd OP1, OP2, OP3 ; shld OP1, OP2, OP3 ; Содержимое первого операнда (OP1) сдвигается на количество разрядов определенное третьим операндов (OP3) разрядов также, как и в командах shr и shl но бит, вышедший за разрядную сетку, не обнуляется, а заполняется содержимым второго операнда, которым может быть только регистр. Циклические сдвиги:
Команда ROL– циклический сдвиг влево: сдвигаем разряд попадает в CF и циклически переносится сдвигаемый влево(вправо в случае ROR). Циклические сдвиги с переносом содержимого Флажка CF:
Для всех команд сдвига флаги ZF, SF, PF устанавливаются в соответствии с результатом. AF – не определен.OF – не определен при сдвигах на несколько разрядов, при сдвиге на 1 разряд в зависимости от команды: - для циклических команд, повышенной точности и sal , shl флаг OF = 1, если после сдвига старший бит изменился; - после sar OF = 0; - после shr OF = значению старшего бита исходного числа. Дополнительные команды: - BT <приемник>, <источник> - BTS <приемник>, <источник> - BTR <приемник>, <источник> - BTC <приемник>, <источник> - BSF <приемник>, <источник> - BSR <приемник>, <источник>
Структуры: Структуры – это сложный тип данных, объединяющий в себе данные различных типов и различной длины. Структура состоит из полей-данных различного типа и длины, занимая последовательные байты памяти. Чтобы использовать переменные типа структура, необходимо вначале описать идентификатор типа структуры, а затем описать переменные такого типа. Описание типа структуры: <имя типа>struc <описание поля> ------------------------ <описание поля> <имя типа>ends <имя типа> - это идентификатор типа структуры, struc и ends - директивы, причем <имя типа > в директиве endsобязательно потому, что endsзакрывает сегмент. Для описания полей используются директивы определения DB, DW, DD и т.д. Имя, указанное в этих директивах, является именем поля, но имена полей не локализованы внутри структуры, т.е. они должны быть уникальными в рамках всей программы, кроме того, поля не могут быть структурами – не допускаются вложенные структуры. Например: TDatastruc ; TData – идентификатор типа yDW 2000 ; y, m, d – имена полей. Значения, указанные mDB ? ; в поле операндов директив DW и DB , dDB 28 ; называются значениями полей, принятыми TDataends ; по умолчанию. ? – означает, что значения по умолчанию нет. На основании описания типа в программу ничего не записывается и память не выделяется. Описание типа может располагаться в любом месте программы, но только до описания переменных данного типа. На основании описания переменных Ассемблером выделяется память в соответствии с описанием типа в последовательных ячейках, так что в нашем случае размещение полей можно представить так: 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) Приоритетными являются начальные значения полей, при описании переменных, т.е. если при описании переменнойдля поля указан ? или какое-либо значение, то значения этих полей по умолчанию игнорируются. 2) если в поле переменной указан знак?, то это поле не имеет начального значения, даже если это поле имеет значение по умолчанию (поле y переменной dt1); 3) Если в поле переменной указано выражение или строка, то значение этого выражения или сама строка становится начальным значением этого поля (поля m и d переменной dt1 и поле y переменной dt2); 4) Если начальное значение поля переменной «пусто» - ничего не указано при описании переменной, то в качестве начального устанавливается значение по умолчанию – значение, указанное при описании типа, если же в этом поле при описании типа стоит знак?, то данное поле не имеет никакого начального значения (поля m переменных dt2 и dt3). 5) Значения по умолчанию устанавливаются для тех полей, которые являются одинаковыми для нескольких переменных одного типа, например, год поступления на факультет одинаков для группы студентов. Любая переменная может изменять свое значение в процессе выполнения программы и поэтому структура может не иметь как значений по умолчанию, так и начальных значений. 6) Отсутствие начального значения отмечается запятой. 7) Если отсутствуют начальные значения нескольких последних полей, то запятые можно не ставить. Если отсутствуют значения первого поля или полей, расположенных в середине списка полей, то запятые опускать нельзя. Например: dt4 TData<1980, ,> можно dt4 TData<1980> dt5 TData<, , 5> нельзя заменить на dt5 TData< 5 >. 8) Если отсутствуют все начальные значения, опускаются все запятые, но угловые скобки сохраняются: dt6 TData<> 9) При описании переменных, каждая переменная описывается отдельной переменной, но можно описать массив структур, для этого в директиве описания переменной указывается несколько операндов и (или) конструкция повторения DUP. Например: dstTData<, 4, 1>, 25 DUP (<>) Описан массив из 26 элементов типа TData, и первый элемент (первая структура) будет иметь начальные значения 2000, 4, 1, а все остальные 25 в качестве начальных будут иметь значения, принятые по умолчанию: 2000, ?, 28. Имя первой структуры dst, второй – dst+4, третьей – dst+8 и т.д. 10) Работать с полями структуры можно также, как с полями переменной комбинированного типа в языках высокого уровня: <имя переменной > .< имя поля> Например, dt1.y, dt2.m, dt3.d В отличие от языков высокого уровня Ассемблер приписывает имени типа и имени переменной размер (тип), равный количеству байтов, занимаемых структурой: typeTData = typedt1 = 4 И это можно использовать при программировании, например, так: ; выполнить побайтовую пересылку dt1 в dt2 movCX, typeTData; количество повторений в CX mov SI, 0 ; i = 0 m: movAL, byteptrdt1[SI]; побайтовая пересылка mov byte ptr dt2[SI], AL; dt1 в dt2 incSI; i = i+1 loopm; использование byteptrобязательно ----------------------------------- 11) Точка, указанная при обращении к полю, это оператор Ассемблера, который вычисляет адрес по формуле: <адресное выражение> +<смещение поля в структуре> Тип полученного адреса совпадает с типом поля, т.е. type (dt1.m) = type m = byte Адресное выражение может быть любой сложности, например: 1) movAX, (dts+8).yтретий элемент массива у поля у 2) mov SI, 8 inc (dts[SI]).m ; Aисп= (dst + [SI]). m = (dst + 8).mсмещение по m внутри структуры 3) lea BX, dt1 mov [BX].d, 10 ; Aисп = [BX] + d = dt1.d Замечания: - type (dts[SI]).m = type (dts[SI].m) = 1, но type dst[SI].m = type dst = 4 - Если при описании типа структуры в директиве, описывающей некоторое поле, содержится несколько операндов или конструкция повторения, то при описании переменной этого типа данное поле не может иметь начального значения и не может быть определено знаком ?, это поле должно быть пустым. Одно исключение: Если поле описано как строка, то оно может иметь начальным значением строку той же длины или меньшей, в последнем случае строка дополняется справа пробелами. Например:student struc f DB 10 DUP (?); фамилия i DB “ ******* “; имя gr DW ?; группа oz DB 5, 5, 5; оценки Studentends Описание переменных: st1 student<“Petrov”, >; нельзя, т.к. поле f не строка st2 student< , “Petr”, 112, > ;можно, f – не имеет начальногозначения st3 student< , “Aleksandra” >; нельзя, в i 10 символов, а допустимо не больше 7 Примеры программ с использованием данных типа структура. 1) ;prim1.asm – прямое обращение к полям структуры Modeltiny Code org 100h; обход 256 байтного префикса пр-го сегмента – PSP… Start: mov AH, 9
Популярное: Почему человек чувствует себя несчастным?: Для начала определим, что такое несчастье. Несчастьем мы будем считать психологическое состояние... Как вы ведете себя при стрессе?: Вы можете самостоятельно управлять стрессом! Каждый из нас имеет право и возможность уменьшить его воздействие на нас... ©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (690)
|
Почему 1285321 студент выбрали МегаОбучалку... Система поиска информации Мобильная версия сайта Удобная навигация Нет шокирующей рекламы |