定义和调用接收不同数据类型的宏时指令操作数大小错误。使用 masm32

Posted

技术标签:

【中文标题】定义和调用接收不同数据类型的宏时指令操作数大小错误。使用 masm32【英文标题】:instruction operands size error when defining and calling a macro that receive different data types. Using masm32 【发布时间】:2019-10-19 15:37:21 【问题描述】:

我正在尝试编写一个宏,它应该接收BYTEWORDDWORD 类型整数并将其打印在屏幕上。我尝试在宏定义中使用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指令操作数大小必须相同

【问题讨论】:

【参考方案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 参数。

【讨论】:

这是 32 位模式,所以我们肯定有 movzx dword, byte 可用,无需使用笨重的 mov eax,0。只需检查大小!= 彼此并使用movzx,否则使用mov。如果movzx 不可编码,则源不是字节或字,也不是会选择mov 的双字。 @PeterCordes:那是来自 OP 的代码。我的回答只是展示如何在编译时对宏参数进行大小/类型检查。 永远记住,寻找问题解决方案的人可能会遇到您的代码并复制/粘贴它。在你的答案中包含糟糕的代码可能会伤害未来的读者。另外movzx 共享一个字节和字的助记符,因此它简化了案例的数量,非常值得一提。

以上是关于定义和调用接收不同数据类型的宏时指令操作数大小错误。使用 masm32的主要内容,如果未能解决你的问题,请参考以下文章

zabbix上的宏(macro)介绍

zabbix上的宏(macro)介绍

在 f2c.h 文件中定义 min() max() 宏时出错

有没有一种方法可以将宏名称作为参数传递给嵌套宏,而不会在扩展最外层的宏时扩展它们?

如何从用户定义的包中正确导入宏?

在 C 或 C++ 中定义结构的宏