Очень часто в программах приходится выполнять действия с числами разного размера, например складывать или умножать байт и слово. Напрямую процессор не умеет выполнять такие операции, поэтому в этом случае необходимо выполнять преобразование типов. Сложность представляет преобразование меньших типов в большие (байта в слово, слова в двойное слово и т.д.)
Преобразовать больший тип в меньший гораздо проще — достаточно отбросить старшую часть. Но такое преобразование небезопасно и может привести к ошибке. Например, если значение слова без знака больше 255, то сделав из него байт, вы получите некорректное значение. Будьте внимательны, если вы используете такие трюки в своей программе.
Преобразование типов без знака
Преобразование типов выполняется по-разному для чисел со знаком и без. Для преобразования чисел без знака необходимо просто заполнить все старшие биты нулями. Например, так будет выглядеть преобразование байта в слово:
Такое преобразование можно выполнить с помощью обычной команды MOV [1] (x объявлен как байт):
mov bl,[x]
mov bh,0 ;BX = x
;Или вот так:
mov bl,[x]
sub bh,bh ;BX = x
Но кроме того в системе команд процессора существует специальная команда — MOVZX [1] (копирование с нулевым расширением). Первый операнд команды имеет размер 16 бит (слово), а второй — 8 бит (байт). Тот же результат можно получить так:
movzx bx,[x] ;BX = x
Преобразование типов со знаком
Для чисел со знаком всё немного сложнее. Если мы просто заполним старшую часть нулями, то результат будет положительным, а это не всегда верно. Поэтому преобразование выполняется путём копирования знакового бита на всю старшую часть. То есть для положительного числа со знаком старшая часть будет заполняться нулями, а для отрицательного — единицами:
Для такого преобразования предназначена команда MOVSX [2] (копирование со знаковым расширением). Первый операнд — слово, второй операнд — байт. Например (y объявлен как байт):
movsx cx,[y] ;CX = y
Существуют ещё две команды для преобразования типов со знаком: CBW [3] (Convert Byte to Word — преобразовать байт в слово) и CWD [4] (Convert Word to Double word — преобразовать слово в двойное слово). У этих команд нет явных операндов. Команда CBW [3] преобразует байт, находящийся в регистре AL, в слово в регистре AX. Команда CWD [4] преобразует слово, находящееся в регистре AX, в двойное слово в регистрах DX:AX. Эти команды удобно использовать вместе с командами умножения и деления. Например:
mov al,[y]
cbw ;AX = y
cwd ;DX:AX = y
Пример программы
Допустим, требуется вычислить значение формулы x = (a + b) / c. Все числа со знаком. Размер x — двойное слово, размер a — байт, размер b и c — слово.
use16 ;Генерировать 16-битный код
org 100h ;Программа начинается с адреса 100h
movsx ax,[a] ;AX = a
add ax,[b] ;AX = a+b
cwd ;DX:AX = a+b
idiv [c] ;AX = (a+b)/c, в DX остаток
cwd ;DX:AX = (a+b)/c
mov word[x],ax ;\
mov word[x+2],dx ;/ x = DX:AX
mov ax,4C00h ;\
int 21h ;/ Завершение программы
;-------------------------------------------------------
a db -55
b dw -3145
c dw 100
x dd ?
Упражнение
Напишите программу для вычисления формулы z = (x·y) / (x + y). Все числа со знаком. Размер x — байт, размер y — слово, размер z — двойное слово. Проверьте работу программы в отладчике. Результаты можете выкладывать в комментариях.