movsb字符串移动指令在NASM正常运行但MASM报错的原因及解决方法
问题分析与解决方案
咱们先把两个汇编器的语法差异理清楚,这就是你遇到问题的核心根源:
为什么NASM能正常运行?
在NASM的语法规则里,当你写mov esi, msg时,NASM会自动将msg解析为这个符号对应的32位内存地址(因为你用的是flat内存模型),相当于直接把字符串的起始地址加载到ESI寄存器,完全符合rep movsb对源地址指针的要求。
MASM报错的原因
MASM的语法逻辑和NASM完全不同:直接使用msg作为操作数时,MASM会默认把它当成内存数据引用——也就是要读取msg地址处的8位字节数据(因为你用db定义了它),而ESI是32位寄存器,8位数据和32位寄存器的操作数大小不匹配,自然就抛出了Error A2022: instruction operands must be the same size错误。
解决办法
你只需要明确告诉MASM,你要加载的是msg和msg2的地址,而不是它们存储的数据,有两种常用的实现方式:
方法1:使用offset关键字
修改报错的两行代码,加上offset来获取符号的地址,让MASM的行为和NASM一致:
.386 .model flat, c .stack 50 .data msg db 'Hello', 0 len equ $ - msg msg2 db len dup(0) .code _start: mov ecx, len ; 这里可以直接赋值,没必要先把ecx设为0再覆盖 mov esi, offset msg mov edi, offset msg2 rep movsb ret end _start
方法2:使用lea指令
lea(Load Effective Address)指令的作用就是计算内存操作数的有效地址并加载到寄存器,效果和offset一致,而且在处理复杂地址计算时更灵活:
.386 .model flat, c .stack 50 .data msg db 'Hello', 0 len equ $ - msg msg2 db len dup(0) .code _start: mov ecx, len lea esi, msg lea edi, msg2 rep movsb ret end _start
另外提个小优化:你原来代码里先mov ecx, 0再mov ecx, len是多余的,直接给ecx赋值len就可以啦。
内容的提问来源于stack exchange,提问作者Lion King
相关产品推荐
相关产品推荐

