CodeNet / Языки программирования / Ассемблер / СПРАВОЧНИК по системе программирования ТУРБО АССЕМБЛЕР 2.0
СПРАВОЧНИК по системе программирования ТУРБО АССЕМБЛЕР 2.0
Преобразование размеров данных
-----------------------------------------------------------------
Иногда бывает необходимо преобразовать слова в байты или на-
оборот. При этом, как и в других действиях, значения могут быть
со знаком или без знака.
Давайте сначала рассмотрим преобразование слова в байт. Это
довольно просто: нужно только избавиться от старшего байта слова.
Например:
.
.
.
mov ax,5
mov bl,al
.
.
.
Здесь значение 5 размером в слово в регистре AX преобразует-
ся в байтовое значение 5 в регистре BL. Конечно, вы должны быть
уверены, что преобразуемое вами значение поместится в байте. По-
пытка преобразовать в байт значение 100h с помощью инструкций:
.
.
.
mov dx,100h
mov al,dl
.
.
.
была бы безуспешной, так как в регистр AL был бы записан только
младший (нулевой) байт.
Преобразование беззнакового байтового значения в слово зак-
лючается просто в обнулении старшего байта слова. Например, инс-
трукции:
.
.
.
mov cl,12
mov al,cl
mov ah,0
.
.
.
преобразуют беззнаковое значение 12 в регистре CL в значение 12
размером в слово в регистре AX.
Преобразование в слово байтового значения со знаком несколь-
ко более сложно, поэтому в процессоре 8086 для выполнения этой
задачи предусмотрена специальная инструкция CBW. Инструкция CBW
преобразует байтовое значение со знаком в регистре AL в значение
со знаком размером в слово в регистре AX. В следующем фрагменте
программы байтовое значение со знаком -1 в регистре DH преобразу-
ется в значение со знаком размером в слово в регистре DX (-1):
.
.
.
mov dh,-1
mov al,dh
cbw
mov dx,ax
.
.
.
В наборе инструкций процессора 8086 для преобразования слова
со знаком в регистре AX в двойное слово со знаком в регистрах DX:
AX (старшее слово содержится в регистре AX) предусмотрена специ-
альная инструкция CWD. Следующие инструкции преобразуют значение
со знаком +10000 (размером в слово), содержащееся в регистре AX,
в значение со знаком +10000 (размером в двойное слово), содержа-
щееся в паре регистров DX:AX:
.
.
.
mov ax,10000
cwd
.
.
.
Беззнаковые значения размером в слово можно преобразовать в
беззнаковые значения размером в двойное слово путем обнуления
старшего слова значения.
Доступ к сегментным регистрам
-----------------------------------------------------------------
Хотя для перемещения значений в сегментные регистры и из них
можно использовать инструкцию MOV, это особый случай, более огра-
ниченный, чем другие случаи использования инструкции MOV. Если
одним из операндов инструкции MOV является сегментный регистр, то
другим операндом должен быть регистр общего назначения или ячейка
памяти. Загрузить константу в сегментный регистр непосредственно
невозможно, и невозможно непосредственно скопировать один сегмен-
тный регистр в другой сегментный регистр.
Так как имена сегментов являются константами, необходимо
загружать сегментные регистры таким же образом, как общие регист-
ры или переменную в памяти. Вот, например, два способа установки
регистра ES в значение сегмента .DATA:
.
.
.
.DATA
DataSeg DW @Data
.
.
.
.CODE
.
.
.
mov ax,@Data
mov es,ax
.
.
.
mov ex,[DataSeg]
.
.
.
Вместо этого хотелось бы сделать следующее:
mov es,@Data ; недопустимо!
но это работать не будет.
Чтобы скопировать содержимое одного сегментного регистра в
другой сегментный регистр, вам придется передать значение через
регистр общего назначения или память. Инструкции:
.
.
.
mov ax,cs
mov ds,ax
.
.
.
и
.
.
.
push cs
pop ds
.
.
.
копируют содержимое регистра CS в DS. Первый метод работает быст-
рее, но при втором методе требуется меньший объем кода.
Не удивляйтесь, при работе с инструкцией MOV вы сталкивае-
тесь с ограничениями, когда дело касается сегментных регистров,
ведь в большинстве инструкций сегментные регистры вовсе не допус-
кается использовать в качестве операндов. Сегментные регистры
можно заносить в стек и извлекать из стека, но этим дело и огра-
ничивается. В операциях сложения, вычитания, логических операциях
или сравнениях их использовать нельзя.
Перемещение данных в стек и из стека
-----------------------------------------------------------------
Со стеком (областью памяти в сегменте стека, работающей по
дисциплине FIFO - "первым-пришел-первым-ушел") вы уже встреча-
лись. На вершину стека всегда указывает регистр SP. Для обращения
к данным в стеке, с использованием режимов адресации памяти, при
которых указателем базы является регистр BP, можно использовать
инструкцию MOV. Например, инструкция:
mov ax,[bp+4]
загружает регистр AX содержимым слова в сегменте стека со смеще-
нием BP+4 (доступ к стеку через регистр BP описывается в Главе
2).
Однако чаще к стеку обращаются с помощью инструкций PUSH и
POP. Инструкция PUSH сохраняет операнд в вершине стека, а инст-
рукция POP извлекает значение из вершины стека и сохраняет его в
операнде. Например, инструкции:
.
.
.
mov ax,1
push ax
pop bx
.
.
.
заносят значение (равное 1) в регистре AX в вершину стека, затем
извлекают 1 из вершины стека и сохраняют ее в BX.
