《深入理解计算机系统》第三版3.3题汇编指令错误咨询
拆解《深入理解计算机系统》3.3题的汇编错误
嘿,刚好我对x86/x86-64的汇编规则门儿清,来逐个帮你解决这些错误,重点说你关心的ebx问题:
1. 为什么movb $0xF, (%ebx)报错说ebx不能用作地址寄存器?
这个问题核心是你当前处于64位(x86-64)汇编模式,而非32位IA-32模式:
- 在32位模式下,
ebx完全可以作为基址寄存器用来寻址,这没问题; - 但到了64位模式(现在大部分系统默认的编译模式),x86-64架构对寻址寄存器做了限制:只能用64位版本的通用寄存器(比如
rbx、rbp、rsp、rdi等)作为基址/变址寄存器,32位寄存器(ebx、eax这类)不能直接用来构建内存地址。
如果你非要用32位寄存器的地址,要么切换到32位编译模式(比如GAS加-m32参数),要么把ebx换成对应的64位寄存器rbx,改成movb $0xF, (%rbx)就正常了。
2. 指令后缀与寄存器ID不匹配的错误
这两个错误都是操作数大小不匹配导致的:
movl %rax, (%rsp):movl是32位(long)操作,但%rax是64位寄存器,后缀和寄存器位数不搭。如果要存64位的rax到栈上,改成movq %rax, (%rsp);如果只需要存rax的低32位,就用movl %eax, (%rsp)。movb %si, 8(%rbp):movb是8位(byte)操作,%si是16位寄存器,源操作数比目标大。要解决的话,要么用8位的子寄存器%sil(si的低8位),改成movb %sil, 8(%rbp);如果要存完整的16位数据,就把后缀换成w(word),改成movw %si, 8(%rbp)。
3. movl %eax, %rdx的目标操作数大小错误
同样是操作数大小不匹配导致的:
movl是32位操作,%rdx是64位寄存器。x86-64里,32位操作会自动把目标64位寄存器的高32位清零,但有些汇编器(比如GAS)会严格要求操作数位数匹配。- 正确的写法要么用32位寄存器对应:
movl %eax, %edx(只写rdx的低32位,高32位自动清零);要么用64位操作:movq %rax, %rdx(把完整的64位rax放到rdx里)。
内容的提问来源于stack exchange,提问作者calebeja9
相关产品推荐
相关产品推荐

