Иллюстрированный самоучитель по Assembler

Использование средств 32-разрядных процессоров в программировании

Структура такого рода программы может выглядеть следующим образом:

0.586
datal segment use16
first dw 7000h dup(')
datal ends
data2 segment use6
second dw 7000h dup (')
data2 ends
data3 segment use16
third dw 7000h dup (')
data3 ends
data4 segment use16
forth dw 7000h dup (')
data4 ends
code segment use16
assume DS:datal,ES:data2,FS:data3,GS:data4
main proc
;Настроим все 4 сегментных регистра на базовые адреса соответствующих сегментов
mov AX,data1; DS › data1
mov word ptr[BX],1111h; Обращение через DS по умолчанию
;Обращение к разным сегментам с явным указанием
;требуемого сегментного регистра (замена сегмента)
mov word ptr ES:[BX],2222h
mov word ptr FS:[BX],3333h
mov word ptr GS:[BX],4444h
;Обращение по именам полей данных разных сегментов с учетом действия директивы assume
mov first,1; Запись в сегмент datal
mov second,2; Запись в сегмент data2
mov third,3; Запись в сегмент data3
mov fourth,4; Запись в сегмент data4
; Перенос данных из сегмента в сегмент
push first
pop second+2
push third
pop fourth+2
…
main endp
code ends

В программе объявлены 4 сегмента данных с именами datal, data2, data3 и data4, содержащие массивы 16-разрядных данных с именами first, second, third и fourth. Длина каждого массива составляет 56 Кбайт, и, таким образом, общий объем данных, доступных программе в любой момент, составляет более 200 Кбайт. Сегменты данных описаны до сегмента команд, что в данном случае имеет значение. В сегменте команд с помощью директивы assume указано соответствие каждому из сегментов своего сегментного регистра (DS, ES, FS и GS). Это даст нам возможность обращаться по именам полей сегментов без явного указания соответствующих этим сегментам сегментных регистров.

Программа начинается с обычной практически для всех программ процедуры настройки всех сегментных регистров. Стоит еще раз повторить, что директива assume лишь обеспечивает правильную трансляцию программы, но не инициализирует сегментные регистры. "Правильная трансляция" в данном случае заключается в том, что при обработке команд, в которых упоминаются имена данных того или иного сегмента, ассемблер автоматически предваряет эти команды, префиксом замены сегмента, выбирая для замены сегментный регистр, указанный в директиве assume для данного сегмента. Так, команда: mov first,1 преобразуется в последовательность кодов (по листингу трансляции):

С7 06 0000r 0001

Где С7 06 – это код команды mov в случае прямой адресации памяти и использования непосредственного операнда, 0000г – смещение адресуемой ячейки, а 0001 – непосредственный операнд (все числа, разумеется, шестнадцатеричные). Здесь нет префикса замены сегмента, потому что адресуется сегмент, которому соответствует регистр DS, используемый процессором по умолчанию.

Однако команды с обращением к другим сегментам транслируются с включением в их коды соответствующих пре фиксов, несмотря на то, что в исходных предложениях не указаны сегментные регистры, а содержатся только ссылки на (уникальные) имена ячеек тех или иных сегментов:

mov second, 2; Код команды 26: С7 06 0000r 0002
mov third, 3;Код команды 64: С7 06 0000r 0003
mov fourth, 4; Код команды 65: С7 06 0000r 0004

Настроив сегментные регистры, мы можем обращаться к полям данных всех четырех сегментов с использованием любых способов адресации. В приведенном фрагменте в регистр ВХ помещается смещение последней ячейки любого из массивов, после чего с помощью косвенной базовой адресации в последние слова всех четырех массивов записываются произвольные числа 1111h, 2222h, 3333h и 4444h. Во всех случаях требуется описатель word ptr, так как по виду команды ассемблер не может определить, хотим ли мы занести в память байт, слово или двойное слово. При обращении к сегментам, адресуемых не через DS, необходимо явное указание сегментного регистра (которое будет преобразовано в код префикса замены сегмента), потому что по виду команды с адресацией через регистры транслятор не может определить, к какому сегменту происходит обращение.

Проще обстоит дело, если в команде указаны имена ячеек сегментов. В этом случае, как уже говорилось выше, транслятор автоматически включает в код команды требуемый префикс замены сегмента.

Наконец, в конце программы приведены строки пересылки данных из сегмента в сегмент через стек. Они убедительны в том отношении, что в четырех последовательных командах производится обращение к четырем различным сегментам программы без перенастройки сегментных регистров, которую пришлось бы выполнить, если бы мы ограничились возможностями МП 86.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.