TASM编写通用数据复制宏报错:操作数大小非法问题求助
解决TASM宏的"Illegal Size"错误并实现多场景数据复制
我来帮你分析这个问题并给出解决方案——你遇到的Argument to operation or instruction has illegal size编译错误,本质是**push/pop指令在16位TASM环境下的操作数大小限制**,你的栈中转思路虽然巧妙,但没法覆盖所有你需要的复制场景,咱们一步步来修正:
错误根源
在8086兼容的16位汇编模式下:
push指令默认操作数为16位,不能直接压入8位内存单元(比如你的var1是db类型,属于8位内存);pop指令同样无法直接弹出到8位内存单元,会触发大小不匹配;- 早期8086 CPU不支持
push立即数,这也会导致你用宏处理立即数到寄存器的场景时出错。
改进后的通用复制宏
我们可以利用TASM的条件汇编特性,根据操作数的类型(寄存器/内存/立即数)和大小(8位/16位)自动选择合适的复制逻辑,完美覆盖你需要的所有场景:
.model small .stack 100h .data var1 db 8h var2 db ? var3 dw 17h var4 dw ? .code start: ; 通用数据复制宏,支持: ; 1. 任意大小立即数到任意寄存器(含段寄存器) ; 2. 8位内存→8位内存 ; 3. 16位内存→16位内存 ; 4. 8位寄存器→8位寄存器 send macro src, dest ; 情况1:立即数到寄存器(含段寄存器) ifidni <src>, <imm> ; 判断src是否为立即数(TASM中立即数会被识别为imm类型) ; 段寄存器不能直接接收立即数,需通过通用寄存器中转 ifidn <type dest>, <word> ; 段寄存器是16位 mov ax, src mov dest, ax else mov dest, src endif ; 情况2:8位内存→8位内存 elseif (type src) eq byte and (type dest) eq byte mov al, src mov dest, al ; 情况3:16位内存→16位内存 elseif (type src) eq word and (type dest) eq word mov ax, src mov dest, ax ; 情况4:8位寄存器→8位寄存器 elseif (type src) eq byte and (type dest) eq byte and (idni <src>, <reg>) and (idni <dest>, <reg>) mov dest, src ; 其他合法场景(比如16位寄存器之间复制) else mov dest, src endif endm ; 测试各种场景 send 0x12, al ; 立即数→8位寄存器 send 0x3456, bx ; 立即数→16位寄存器 send 0x7890, ds ; 立即数→段寄存器 send var1, var2 ; 8位内存→8位内存 send var3, var4 ; 16位内存→16位内存 send ah, cl ; 8位寄存器→8位寄存器 ; 程序退出 mov ah, 04ch int 21h end start
关键说明
- 条件汇编指令:使用
ifidni(忽略大小写的字符串比较)、type(获取操作数类型大小)来判断场景; - 段寄存器处理:由于8086不支持直接将立即数mov到段寄存器,所以先把立即数加载到通用寄存器(比如
ax),再中转到段寄存器; - 内存到内存复制:x86汇编不支持直接的内存到内存mov指令,必须通过通用寄存器中转,这也是你的原宏无法处理8位内存复制的核心原因。
编译验证
将上述代码保存为.asm文件,用TASM编译:
tasm yourfile.asm tlink yourfile.obj
此时不会再出现"Illegal Size"错误,所有复制场景都能正常工作。
内容的提问来源于stack exchange,提问作者Dmitry Sokolov
相关产品推荐
相关产品推荐

