assembler. Учебник для вузов_Юров В.И_2003 -637с (862834), страница 36
Текст из файла (страница 36)
На данном этапе изучения ассемблера не стоит пытаться разобраться с ним, но впоследствии обязательно стоит к нему вернуться.Работа с адресами и указателямиПри написании программ на ассемблере производится интенсивная работа с адресами операндов, находящимися в памяти. Для поддержки такого рода операцийесть специальная группа команд, в которую входят следующие команды.ii lea <приемник>,<источник> — загрузка эффективного адреса;ж Ids <приемник>,<источник> — загрузка указателя в регистр сегмента данных ds;я les <приемник>,<источник> — загрузка указателя в регистр дополнительного сегмента данных es;Работа с адресами и указателями157я Igs <приемник>,<источник> — загрузка указателя в регистр дополнительного сегмента данных gs;* Ifs <приемник>,<источник> — загрузка указателя в регистр дополнительного сегмента данных fs;ii Iss <приемник>,<источник> — загрузка указателя в регистр сегмента стека ss.Команда LEA похожа на команду MOV тем, что она также производит пересылку,однако команда LEA производит пересылку не данных, а эффективного адреса данных (то есть смещения данных относительно начала сегмента данных) в регистр,указанный операндом <приемник>.Часто для выполнения некоторых действий в программе недостаточно знатьзначение одного лишь эффективного адреса данных, а необходимо иметь полныйуказатель на данные.
Вы помните, что полный указатель на данные состоит из сегментной составляющей и смещения. Все остальные команды этой группы позволяют получить в паре регистров такой полный указатель на операнд в памяти. Приэтом имя сегментного регистра, в который помещается сегментная составляющаяадреса, определяется кодом операции. Соответственно, смещение помещаетсяв регистр общего назначения, указанный операндом <приемник>. Но не все так просто с операндом <источник>. На самом деле в команде в качестве источника нельзяуказывать непосредственно имя операнда в памяти, на который мы бы хотели получить указатель.
Предварительно необходимо получить само значение полногоуказателя в некоторой области памяти и задать в команде получения полного адреса имя этой области. Для выполнения этого действия необходимо вспомнитьдирективы резервирования и инициализации памяти (см. главу 5). При применении этих директив возможен частный случай, когда в поле операндов указываетсяимя другой директивы определения данных (фактически, имя переменной).
В этомслучае в памяти формируется адрес этой переменной. Какой адрес будет сформирован (эффективный или полный), зависит от применяемой директивы. Если этоDW, то в памяти формируется только 16-разрядное значение эффективного адреса, если же DD — в память записывается полный адрес. Размещение этогоадреса в памяти следующее: в младшем слове находится смещение, в старшем —16-разрядная сегментная составляющая адреса. Посмотрите на листинг 5.3и рис. 5.20 (глава 5). В сегменте данных программы из листинга 5.3 переменныеadr и adr_full иллюстрируют наш случай получения частичного и полного указателей на данные в памяти.Например, при организации работы с цепочкой символов удобно поместить ееначальный адрес в некоторый регистр и далее в цикле модифицировать это значение для последовательного доступа к элементам цепочки.
В листинге 7.2 производится копирование строки байтов str_l в строку байтов str_2. В строках 13 и 14в регистры SI и DI загружаются значения эффективных адресов переменных str_lи str_2. В строках 18,19 производится пересылка очередного байта из одной строки в другую. Указатели на позиции байтов в строках определяются содержимымрегистров SI и DI. Для пересылки очередного байта необходимо увеличить на единицу регистры SI и DI, что и делается командами сложения ШС (строки 20,21).
Послеэтого программу необходимо зациклить до обработки всех символов строки.1 58Глава 7. Команды обмена даннымиЛистинг 7. 2. Копирование строки<1>; - Prg_7_2.asm <2> masm<3> model small<4> .data<5> ...<6> str_l db "Ассемблер - базовый язык компьютера"<7> str_2 db 35 dup (" ")<8> full_pnt dd str_l<9> ...<10>.code<11>start:<13><14><15><16><17><18><19><20><21><22><23>ml:lealealesmovsi ,str_ldi ,str_2bx,full_pnt ;полный указатель на strl в пару es:bxex, 35;счетчик цикла для loop ml (глава 10)mov al , [si ]mov [di] ,alinc siinc di;цикл на метку ml до пересылки всех символов (loop ml)<24>end startНеобходимость использования команд получения полного указателя данныхв памяти, то есть адреса сегмента и значения смещения внутри сегмента, возникает, в частности, при работе с цепочками.
Мы рассмотрим этот вопрос в главе 12.В строке 8 листинга 7.2 в двойном слове fulLpnt формируются сегментная частьадреса и смещение для переменной str_l. При этом два байта смещения занимаетмладшее слово fulLpnt, а значение сегментной составляющей адреса — старшееслово fulLpnt. В строке 15 командой LES эти компоненты адреса помещаются в регистры ВХ и ES.Преобразование данныхК группе команд преобразования данных можно отнести множество команд процессора, но большинство из них имеют те или иные особенности, которые требуютотнести их к другим функциональным группам (см. рис 3.3). Поэтому из всей совокупности команд процессора непосредственно к командам преобразования данных можно отнести только одну командуx l a t [адрес_таблицы_перекодировки]Это очень интересная и полезная команда.
Ее действие заключается в том, чтоона замещает значение в регистре AL другим байтом из таблицы в памяти, расположенной по адресу, указанному операндом адрес_таблицы_перекодировки. Слово «таблица» весьма условно; по сути, это просто строка байтов. Адрес байта в строке,которым будет производиться замещение содержимого регистра AL, определяетсясуммой (ВХ) + (AL), то есть содержимое AL играет роль индекса в байтовом массиве.При работе с командой XLAT обратите внимание на следующий тонкий момент.Хотя в команде указывается адрес строки байтов, из которой должно быть извлечено новое значение, этот адрес должен быть предварительно загружен (например, с помощью команды LEA) в регистр ВХ.
Таким образом, операнд адрес_табли-Преобразование данных1 59цы_перекодировки на самом деле не нужен (на это указывают квадратные скобки).Что касается строки байтов (таблицы перекодировки), то она представляет собойобласть памяти размером от 1 до 255 байт (диапазон числа без знака в 8-разрядномрегистре).В качестве иллюстрации работы данной команды мы рассмотрим программуиз листинга 6. 1 (см. главу 6). Вы помните, что эта программа преобразовывала двузначное шестнадцатеричное число, вводимое с клавиатуры (то есть в символьномвиде), в эквивалентное двоичное представление в регистре AL. В листинге 7.3 приведен вариант этой программы с использованием команды XLAT.Листинг 7.3.
Использование таблицы перекодировкиPrg_7_3.asm__<2> ;Программа преобразования двузначного шестнадцатеричного числа<3> ;в двоичное представление с использованием команды xlat.<4> ;Вход: исходное шестнадцатеричное число; вводится с клавиатуры.<5> ;Выход: результат преобразования в регистре al<6> masm<7> model small<8> .data;сегмент данных<9> message db "Введите две шестнадцатеричные цифры, $"<10> tabldb 48 dup(O) ,6, 1.2,3 . 4 .
5 . 6 . 7 , 8 . 9 . 7 dup (0)<11>db 0ah,0bh,0ch,0dh,0eh,0fh, 26 dup (0)<12>db 0ah,0bh,0ch,0dh,0eh,0fh, 152 dup (0)<13>. s t a c k 256;сегмент стека<14>.code<15>;начало сегмента кода<16>main proc; начало процедуры main<17>mov ax,@data :физический адрес сегмента данных в регистр ах<18>mov d s . a x;ax записываем в ds<19>lea b x . t a b l ; з а г р у з к а адреса строки байт в регистр Ьх<20>mov ah, 9<21>mov dx, o f f s e t message<22>int 21h;вывести приглашение к вводу<23>хог а х , ах;очистить регистр ах<24>mov ah, In;значение lh в регистр ah<25>int 21h; вводим первую цифру в al<26>xlat; перекодировка первого введенного символа в al<27>mov dl.al<28>shl dl,4;cflBnr dl влево для освобождения места для младшей цифры<29>int 21h;ввод второго символа в al<30>xlatперекодировка второго введенного символа в al<31>add al.dlскладываем для получения результата<32>mov а х , 4c00h; пересылка 4c00h в регистр ах<33>int 21h;завершение программы<34>endp main;конец процедуры main<36>end main; конец программы с точкой входа mainСама по себе программа проста; сложность вызывает обычно формированиетаблицы перекодировки.