Иванова Г.С., Ничушкина Т.Н. - Основы программирования на ассемблере IA-32 (1075571), страница 7
Текст из файла (страница 7)
Команда записи строки STOS.STOSB(запись байта),STOSW(запись слова),STOSD(запись двойного слова)Команда записывает в основную память содержимое AL, АХ или EAX соответственно. Для адресации операнда используются регистры ES:EDI.3. Команда пересылки MOVS.MOVSB(пересылка байта),МОVSW(пересылки слова),МОVSD(пересылки двойного слова).Оглавление50Команда пересылает элемент строки из области, адресуемой регистрами DS:ESI, вобласть, адресуемую регистрами ЕS:EDI.4.
Команда сканирования строки SCAS.SCASB(поиск байта),SCASW(поиск слова).SCASD(поиск двойного слова).По команде содержимое регистра AL, АХ или EAX сравниваются с элементомстроки, адресуемым регистрами DS:SI, и устанавливается значение флажков в соответствии с результатом [DI] - AL или [DI]-AX.5. Команда сравнения строк CMPS.СMPSB(сравнение байт),СMPSW(сравнение слов),СMPSD(сравнение двойных слов).По команде элементы строк, адресуемых парами регистров DS:ESI и ES:EDI, сравниваются и устанавливаются значения флажков в соответствии с результатом [EDI][ESI].6.
Префиксная команда повторения.REPКомандаКоманда позволяет организовать повторение указанной команды ECX раз.Пример:repstosbЗдесь поле, адресуемое парой регистров ES:EDI длиной ECX заполняется содержимым AL.7. Префиксные команды «повторять, пока равно» и «повторять, пока неравно».REPEКомандаREPNE КомандаПрефиксные команды используются совместно с командами СMPS и SCAS. Префикс REPE означает повторять, пока содержимое регистра EСХ не равно нулю и значение флажка нуля равно единице, a REPNE – повторять, пока содержимое регистра ECXне равно нулю и значение флажка нуля равно нулю.Оглавление51Контрольные вопросы1.Напишите фрагмент программы, реализующей ветвление.
Почему при написа-нии фрагмента использованы команды условной и безусловной передачи управления?Ответ.2.Напишите фрагмент программы, реализующей итерационный цикл. Почемупри написании фрагмента использованы команды условной и безусловной передачиуправления?Ответ.3.Как в ассемблере моделируется обработка массивов и матриц? Почему?Ответ.4.В чем состоит особенность определения местонахождения операндов строко-вой обработки? С чем связана такая реализация?Ответ.Оглавление524Более сложные машинные команды ассемблера4.1Команды манипулирования битами1. Логические команды.NOTОперанд ; логическое НЕ;ANDОперанд1, Операнд2 ; логическое И;ORОперанд1, Операнд2 ; логическое ИЛИ;XORОперанд1, Операнд2 ; исключающее ИЛИ;TESTОперанд1, Операнд2 ; И без записи результата.Операнды байты или слова.Пример.
Выделить из числа в AL первый бит:andal,10000000B2. Команды сдвигаКод операции Операнд, СчетчикСчетчик записывается в регистр СL. Если счетчик равен 1, то его можно записатьв команду.Коды команд сдвига:SAL, SHL – сдвиг влево арифметический и логический;SAR, SHR – сдвиг вправо арифметический и логический;ROL, ROR – сдвиг влево и вправо циклический;RCL, RCR– сдвиг циклический влево и вправо с флагом переноса;Пример.
Умножить число в AX на 10:movbx,axshlax,1shlax,1addax,bxshlax,1Оглавление534.2Организация ввода – вывода в консольном режимеБиблиотека MASM32.lib содержит специальные подпрограммы организации вводавывода для консольного режима.Ввод. Процедура ввода:StdInPROClpszBuffer:DWORD, bLen:DWORDПервый операнд – адрес буфера ввода, второй – размер буфера ввода (до 128 байт).При вызове процедуры компьютер переходит в состояние ожидания ввода с клавиатуры. Ввод завершается при нажатии клавиши «Enter». В буфере ввода после завершенияоперации находятся коды введенных символов. Строка завершается маркером концастроки (0Dh,0Ah), например, если пользователь ввел символы «+ 123» (между плюсом и1 введен один пробел), то содержимое буфера в шестнадцатеричном виде будет следующим:2B 20 31 32 33 0D 0A , где 2В16 – код ANSI символа «+», а 2016 – код пробела.Таким образом, если пользователь ввел пробел, знак, буквы или цифры, то в буферебудут находиться их шестнадцатеричные коды.Таким образом, при программировании операций ввода на ассемблере приходитсяосуществлять преобразования чисел из символьного представления во внутренний формат.
Для целых чисел – это двоичный формат с фиксированной точкой, согласно которому отрицательные числа должны быть записаны в дополнительном коде.Для облегчения преобразования во внутренний формат целесообразно оговоритьвозможные варианты ввода чисел в символьном виде, например, может или не можетбыть введен знак, возможны ли пробелы перед числом и т. д.Алгоритм преобразования основан на схеме Горнера:<число>:=<число>*10+<цифра>.Алгоритм преобразования для положительных чисел без знака следующий:Число:=0Ввести Код цифрыЦикл-пока Код цифры≠0DhЦифра:=Код цифры – 30hОглавление54Число:=Число*10 + ЦифраВвести Код цифрыВсе-циклЕсли число со знаком или формат ввода допускает наличие пробелов, то это должнообрабатываться отдельно.Библиотеки ассемблера содержать специальные подпрограммы преобразования, которые также могут быть использованы.Процедура замены маркера конца строки (0Dh,0Ah) нулем:StripLFPROClpszBuffer:DWORDПараметр – адрес буфера ввода.
После выполнения процедуры введенная строка будет завершаться нулем, например, для примера, приведенного выше, это будет:2B 20 31 32 33 00 0A .Что позволит для преобразования числа использовать стандартную функцию из библиотеки С++.Функция преобразования завершающейся нулем строки в число:atolPROClpszBuffer:DWORD ; результат – в EAXДля вызова функции необходимо, чтобы:1)был подключен файл, содержащий описание прототипа этой функции, для стан-дартных функций это, как правило, файлы kernel32.inc и masm32.inc:Include kernel32.incInclude masm32.inc2)был подключен файл библиотеки, содержащий оттранслированный текст функ-ции, для стандартных функций это, как правило, файлы kernel32.lib и masm32.lib:IncludeLib kernel32.libIncludeLib masm32.libВызов осуществляется макрокомандой Invoke:INVOKE Имя процедуры или ее адрес [, Список аргументов ]При указании аргументов часто используются атрибуты полей данных:ADDR <Имя поля данных> – возвращает ближний или дальний адрес переменной в зависимости от модели памяти – для Flat ближний;Оглавление55OFFSET <Имя поля данных> – возвращает смещение переменной относительноначала сегмента – для Flat совпадает с ADDR;TYPE <Имя поля данных> – возвращает размер в байтах элемента описанныхданных;LENGTHOF <Имя поля данных> – возвращает количество элементов, заданныхпри определении данных;SIZEOF <Имя поля данных> – возвращает размер поля данных в байтах.Пример.
Программа ввода числа.DATAzaprosDB'Input value:',13,10,0 ; запросbufferDB10 dup ('0'); буфер ввода.CODE. . .vvod:Invoke StdOut,ADDR zaprosInvoke StdIn,ADDR buffer,LengthOf bufferInvoke StripLF,ADDR buffer; Преобразование в SDWORDInvoke atol,ADDR buffer ;результат в EAX. . .Вывод. При выводе решается обратная задача: необходимо преобразовать число,представленное во внутреннем формате, в символьную строку, завершающуюся нулем.Обратное преобразование из внутреннего формата в символьный обычно используетстандартное правило перевода числа из двоичной системы счисления в десятичную: деление на 10 с выделением остатков.
В этом случае десятичные цифры получаются вобратном порядке. Если среди выводимых чисел могут быть отрицательные, то необходимо предусмотреть специальную проверку и преобразовывать отрицательные числа впрямой код.Гораздо проще для этого применить стандартную процедуру.Процедура преобразования числа в строку:dwtoaPROCpublic dwValue:DWORD, lpBuffer:PTR BYTEОглавление56Первый параметр – целое число формата DWORD, второй – адрес буфера, размером16 байт. Полученная после преобразования строка обычно короче 16 символов, так как несодержит незначащих нулей.Процедура вывода завершающейся нулем строки в окно консоли:StdOutPROClpszBuffer:DWORDПараметр – адрес буфера вывода.Пример. Программа вывода числа.DATA; поле результатаresultDWORD ?stringDB13,10,'Result =' ; заголовок выводаresstrDB16 dup (?); выводимое число-строка.CODE ...; Преобразование числа в символьную строкуInvoke dwtoa,result,ADDR resstr; Вывод заголовка и результата-строкиInvoke StdOut,ADDR string.
. .Пример. Программа ввода и вывода элементов массива с преобразованием вовнутреннее представлениеНаписать программу ввода массива из 10 чисел размером двойное слово и выводатого же массива. Числа должны вводиться каждое в своей строке. Вывод всех чисел должен осуществляться в одну строку через пробелы. Перед отрицательными числами необходимо выводить знак "-"..586 ; разрешает использование набора команд i80586.MODELflat, stdcall ; определяет модель памяти и тип связиOPTION CASEMAP:NONE ;чувствительность идентификаторов к региструInclude kernel32.inc ; подключает файлы описаний библиотечных; процедур и функцийInclude masm32.incIncludeLib kernel32.lib ; подключает библиотекиIncludeLib masm32.lib; на этапе компоновкиОглавление57; сегмент инициализированных данных.DATAMsgDB"Press Enter to Exit",0AH,0DH,0InputMsg DB"Input integer value",0AH,0DH,0OutputMsg DB"Results:",0AH,0DH,0pustoDB" ",0nlDB0AH,0DH,0; сегмент неинициализированных данных.DATA?inbufDBaSDWORD 10 DUP (?)stringDB.STACK100 DUP (?)16 DUP (?); сегмент кода.CODEStart:cycle:; сегмент стека - 4096 байт4096movECX,10movEBX,0pushECXInvoke StdOut,ADDR InputMsg ; вывод запросаInvoke StdIn,ADDR inbuf,LengthOf inbuf ; ввод числаInvoke StripLF,ADDR inbufInvoke atol,ADDR inbufmova[EBX*4],EAXincEBXpopECXloopcycleInvoke StdOut,ADDR OutputMsg ; вызов процедуры выводаcycle2:movECX,10movEBX,0pushECXInvoke dwtoa,a[EBX*4],ADDR string; преобразование числа в символьную строкуInvoke StdOut,ADDR string ; вывод результата-строкиInvoke StdOut,ADDR pusto ; вывод пробелаОглавление58incEBXpopECXloopcycle2Invoke StdOut,ADDR nl ; вывод маркера конца строкиInvoke StdOut,ADDR Msg ; вызов процедуры выводаInvoke StdIn,ADDR inbuf,LengthOf inbuf; вызов процедуры вводаInvoke ExitProcess,0END; вызов процедуры завершенияStartОглавление59Контрольные вопросы1.Какие команды относятся к командам манипулирующим с битами?Ответ.2.Как реализованы команды ввода-вывода?Ответ.Оглавление60Литература1.Ирвин К.
Язык ассемблера для процессоров Intel. – М.: Изд. дом «Вильямс», 2005.2. Зубков С.В. Assembler для DOS, Windows и Unix. – М.: ДМК Пресс, 2004.3. Пирогов В.Ю. Ассемблер. Учебный курс. – СПб.: БХВ-Петербург, 2003.4. Финогенов К.Г., Рудаков П.И. Язык Ассемблера: уроки программирования. – М.:Диалог-МИФИ, 2001.5.Юров В.И.
Справочник по языку Ассемблера IBM PC. – CПб.: Питер, 2004.Оглавление.