12. Команды расширения

В программах довольно часто нужно переслать меньшее по длине значение в большую по длине переменную или регистр. В качестве примера предположим, что нам нужно загрузить 16-разрядное беззнаковое значение, хранящееся в переменной count, в 32-разрядный регистр ЕСХ. Самое простое решение этой задачи заключается в том, что вначале нужно обнулить регистр ЕСХ, а затем загрузить 16-разрядное значение переменной count в регистр СХ:

mov ecx, 0
mov cx, unsignedVal ; ECX = FFFFFFF0h (-16)

А что делать, если нужно загрузить в регистр ЕСХ отрицательное значение, например, -16? для получения правильного результата нам нужно было не обнулять регистр ЕСХ, а загрузить в него значение FFFFFFFFh, и только затем загрузить в регистр СХ переменную signedVal. Код будет выглядеть так:

mov ecx, 0FFFFFFFFh
mov cx, signedVal ; ECX = FFFFFFF0h (-16)

Тобишь, для решения задачи, вначале нужно проанализировать знак числа и в зависимости от результата загрузить в регистр либо 0, либо -1.

Для выполнения расширения можно использовать готовые команды:

Команда CBW (Convert byte to word)
Выполняет преобразование значения, находящегося в регистре al, до размера слова, и помещает его в ах, при этом свободные старшие биты ах заполняются знаковым битом al (al -> ax).

Результат выполнения для отрицательного и положительного числа
Mov al, -1; al =  10000001b
Cbw; ax = 11111111 10000001b 

Mov al, 1; al =  00000001b
Cbw; ax = 00000000 00000001b 

Команда CWD (Convert word to double)
Выполняет преобразование значения, находящегося в регистре ax, до размера двойного слова, и помещает его в пару регистров dx:ах, при этом свободные биты dx заполняются знаковым битом aх. (ax -> dx:ax)

Mov ax, -1; ax =  10000000 00000001b
Cwd; dx 11111111 11111111   ax =  10000000 00000001b

Mov ax, 1; ax =  00000000 00000001b
Cwd; dx = 00000000 00000000 ax =  0000000 00000001b

Команда CWDE (Convert word to double extended)
Выполняет преобразование значения, находящегося в регистре ax, до размера двойного слова, и помещает его в регистр eах, при этом свободные старшие биты eax заполняются знаковым битом aх. (ax -> eax)

Mov ax, -1; ax =  10000000 00000001b
Cwde; eax = 11111111 11111111 10000000 00000001b

Mov ax, 1; ax =  00000000 00000001b
Cwde; eax = 00000000 00000000 00000000 00000001b

Команда CDQ (Convert double to quadruple)
Выполняет преобразование значения, находящегося в регистре eax, до размера учетверенного слова, и помещает его в пару регистров edx:eах, при этом свободные биты edx заполняются знaковым битом eax. (eax -> edx:eax)

Mov eax, -1; eax =  10000000 00000000 00000000 00000001b
Cdq; 
;edx =  11111111 11111111 11111111 11111111b
 ;eax =  10000000 00000000 00000000 00000001b

Mov eax, 1; eax =  00000000 00000000 00000000 00000001b
Cdq; 
;edx =  00000000 00000000 00000000 00000000b
 ;eax =  00000000 00000000 00000000 00000001b

Команда MOVZX
Команда MOVZX копирует содержимое исходного операнда в больший по размеру регистр получателя данных. При этом оставшиеся неопределенными биты регистра-получателя (как правило, старшие 16 или 24 бита) сбрасываются в ноль. Эта команда используется только при работе с беззнаковыми целыми числами.

Команда MOVSX
Команда MOVSX (Move With Sign-Extend, или Переместить и дополнить знаком) копирует содержимое исходного операнда в больший по размеру регистр получателя данных, также как и команда MOVZX. При этом оставшиеся неопределенными биты регистра- получателя (как правило, старшие 16 или 24 бита) заполняются значением знакового бита исходного операнда. Эта команда используется только при работе со знаковыми целыми числами.

Команды MOVSX и MOVZX применимы к следующим операндам:
MOVSX/MOVZX 16-разрядный регистр (16r), 8-разрядный регистр или поле памяти(8r/8m)
MOVSX/MOVZX 32-разрядный регистр (32r), 8-разрядный регистр или поле памяти(8r/8m)
MOVSX/MOVZX 32-разрядный регистр (32r), 16-разрядный регистр или поле памяти(16r/16m)

17.07.2015