Использование средств 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.