Как это:
; Before:
; Result is in DX:AX on the form ABCD:EFGH
; EAX = ????EFGH : AX contains EFGH, upper part of EAX has unknown content
; EDX = ????ABCD : DX contains ABCD (the 16 most siginficant bits
; of the multiplication result)
; like with EAX the upper (=most siginifcant)
; 16 bits of EDX also has unknown content.
and eax, 0x0000ffff ; clear upper bits of eax
; EAX = 0000EFGH
shl edx, 16 ; shift DX into position (will just shift the upper 16 junk bits away)
; EDX = ABCD000
or eax, edx ; combine in eax
; EAX = ABCDEFGH
Причина, по которой это работает, в том, что ax
относится к 16 младшим значащим битам eax
. Подробнее см. этот ТАК вопрос и принятый ответ. Этот метод также будет работать для imul
, но обычно вы должны быть осторожны при работе с числами со знаком в коде сборки.
Полный пример:
bits 32
extern printf
global main
section .text
main:
push ebx
mov ax, 0x1234
mov bx, 0x10
mul bx
and eax, 0x0000ffff ; clear upper bits of eax
shl edx, 16 ; shift DX into position
or eax, edx ; and combine
push eax
push format
call printf
add esp, 8
mov eax, 0
pop ebx
ret
section .data
format: db "result = %8.8X",10,0
Компилировать с:
nasm -f elf32 -g -o test.o test.asm
gcc -m32 -o test test.o
Обновление:
На 32-битных машинах обычно проще и предпочтительнее работать с 32-битными значениями, если это целесообразно в контексте. Например:
movzx eax, word [input1] ; Load 16-bit value and zero-extend into eax
movzx edx, word [input2] ; Use movsx if you want to work on signed values
mul eax, edx ; eax *= edx
Что также показывает использование одной из более новых, более простых в использовании инструкций mul
. Вы также можете сделать то же, что и сейчас, и mov ax, [input1]
, а затем увеличить размер с помощью movzx eax, ax
.