寻址方式(Addressing Modes)

AT&T 内存操作数通用格式:

section:disp(base, index, scale)

等价于地址:section_base + disp + base + index * scale

  • disp:偏移常量(十进制或十六进制 0x...),可以是符号。
  • base:基址寄存器。
  • index:变址寄存器。
  • scale:1、2、4 或 8(index 的乘数,缺省为 1)。
  • 各部分均可省略,但括号与逗号结构需保留。

常见形式

形式 示例 含义
直接(绝对地址) movl value, %eax 地址 value 处的值
寄存器间接 movl (%eax), %ebx *eax
带偏移 movl 8(%ebp), %eax *(ebp+8)
变址 movl (%ebx,%ecx), %eax *(ebx+ecx)
变址+比例 movl (%ebx,%ecx,4), %eax *(ebx+ecx*4)
偏移+变址+比例 movl 12(%ebx,%ecx,4), %eax *(ebx+ecx*4+12)
无基址变址 movl arr(,%ecx,4), %eax *(arr+ecx*4)
RIP 相对(64 位) leaq msg(%rip), %rdi rip + msg 的偏移(PIC 常用)

注意事项

  • 内存到内存操作不被允许:两个操作数不能都是内存,需经寄存器中转。
  • scale 只能是 1/2/4/8,省略时默认为 1:(%ebx,%ecx) 是合法的(base+index,scale 默认 1);但 (%ebx+%ecx) 这种"寄存器相加"写法非法。
  • 64 位模式下请使用 64 位寄存器寻址。使用 32 位寄存器(如 (%eax,%ebx))虽然能汇编,但会生成地址大小前缀(address-size override),有效地址被截断为 32 位,容易出错。
  • %rsp 不能用作 index 寄存器;%rip 只能以 disp(%rip) 的形式出现,不能作 base/index。
  • 64 位模式下直接绝对寻址(如 movl 0x8049000, %eax)使用符号扩展的 32 位位移,地址超出低 2GB/高 2GB 范围会出错。要访问任意地址,先把地址装入寄存器:movabsq $0x1122334455667788, %raxmovl (%rax), %eax(非 PIC 场景)。
  • 只有 mov 接受 64 位立即数:movq $0x1122334455667788, %rax(汇编器实际生成 movabs)。
# 遍历数组(每个元素 4 字节)
    movl $0, %ecx
loop:
    movl arr(,%rcx,4), %eax    # arr[rcx]
    addl $1, %ecx
    cmpl $4, %ecx
    jl   loop

段前缀

movl %fs:0, %eax        # 从 fs 段偏移 0 处读取(线程局部存储常用)