Ошибка размера операндов инструкции при определении и вызове макроса, получающего разные типы данных. Использование masm32

Я пытаюсь написать макрос, который должен получать целое число типа BYTE, WORD или DWORD и печатать его на экране. Я пытаюсь использовать функцию SIZEOF в определении макроса, чтобы отправлять разные типы данных в регистры разного размера, но ошибка возникает при вызове макроса. Вот полный код:

INCLUDE Irvine32.inc
.data
oneByte BYTE 42h
twoByte WORD 1423h
fourByte DWORD 1950123Dh
errorMessage BYTE "ERROR INPUT!!!", 0
.code
mWriteInt MACRO theInt
    mov eax, sizeof theInt
    cmp eax, 1
    je isonebyte
    cmp eax, 2
    je istwobyte
    cmp eax, 4
    je isfourbyte
    jmp error
isonebyte:
    mov eax, 0
    mov al, theInt
    jmp over
istwobyte:
    mov eax, 0
    mov ax, theInt
    jmp over
isfourbyte:
    mov eax, theInt
    jmp over
error:
    mov edx, offset errorMessage
    call WriteString
    call crlf
over:
    call writeInt
ENDM

MAIN PROC
mWriteInt oneByte   ;<----ERROR HAPPENS HERE
call dumpregs
MAIN ENDP
END MAIN

сообщение об ошибке показывает: Операнды инструкции A2022 должны быть одинакового размера Операнды инструкции A2022 должны быть одинакового размера


person Irrawa    schedule 19.10.2019    source источник


Ответы (1)


Ваш текущий подход к проверке размера во время выполнения требует, чтобы ассемблер сгенерировал машинный код для всех возможных путей кода, даже тех, которые могут не выполняться во время выполнения.

Если один или несколько из этих путей кода приводят к недопустимым комбинациям операндов, то, очевидно, это не удастся.

Вам придется переместить проверку размера, чтобы она выполнялась во время компиляции. Что-то вроде:

IF SIZEOF theInt EQ SIZEOF BYTE
    mov eax, 0
    mov al, theInt
ELSEIF SIZEOF theInt EQ SIZEOF WORD
.. etc ..
ENDIF
call writeInt

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

push theInt
pop eax
call writeInt

Изменить: этот подход не работает для r/m8 аргумента.

person Michael    schedule 21.10.2019
comment
Это 32-битный режим, поэтому у нас определенно есть movzx dword, byte, не нужно использовать неуклюжий mov eax,0. Просто проверьте размеры! = Друг друга и используйте movzx, иначе mov. Если movzx не кодируется, значит, источником не было ни байта, ни слова, ни двойного слова, которое могло бы быть выбрано mov. - person Peter Cordes; 21.10.2019
comment
@PeterCordes: Это было из кода OP. Мой ответ заключался в том, чтобы показать, как выполнять проверку размера / типа параметров макроса во время компиляции. - person Michael; 21.10.2019
comment
Всегда помните, что кто-то, ищущий решение проблемы, может натолкнуться на ваш код и скопировать / вставить его. Использование плохого кода в ваших ответах может навредить будущим читателям. Также movzx использует мнемонику для байта и слова, что упрощает количество случаев, о чем стоит упомянуть. - person Peter Cordes; 21.10.2019