Skip to content

程序结构和执行

约 837 字大约 3 分钟

2024-11-02

AT&T汇编

AT&T汇编语法

指令 源操作数 目的操作数

描述内存中的位置:

  • Intel: QWORD PTR[rbx]
  • AT&T: (%rbx)

数据大小

位数名称缩写
16位WORD
32位双字DWORD
64位四字QWORD

通用寄存器

x86-64 提供了16个通用寄存器:

寄存器用途备注
rax返回值eax, ax, al
rbx被调用者保存
rcx第四个参数
rdx第三个参数
rsi第二个参数esi, si, sil
rdi第一个参数
rbp栈底指针
r8第五个参数r8d, r8w, r8b
r9第六个参数
r10被调用者保存
r11被调用者保存
r12被调用者保存
r13被调用者保存
r14被调用者保存
r15被调用者保存

mov 指令

MOV指令格式

MOV S D将源操作数S传送到目的操作数D

  • 源操作数:立即数、寄存器或内存
  • 目的操作数:寄存器或内存地址
  • 目的操作数不能是立即数

movabsq指令用于移动64位立即数:

movabsq $0x0011223344556677, %rax
# %rax = 0x0011223344556677

注意

指令需要指明移动寄存器的部分大小(b,w,l,q)。movl以寄存器为目的寄存器时会把寄存器的高四位设置为0。

数据扩展

指令说明
MOVS以0填充高位
MOVZ以符号位填充高位

cltq 指令:符号位扩展 %eax -> %rax

示例

long exchange(long *xp, long y) {
    long x = *xp;
    *xp = y;
    return x;
}
# long exchange(long *xp, long y)
# xp in %rdi, y in %rsi
exchange:
    movq (%rdi), %rax   # 取%rdi地址指向的内存空间的值传送给%rax
    movq %rsi, (%rdi)   # 将%rsi寄存器存储的值移动到%rdi寄存器值所指向的内存中
    ret

栈操作

push和pop指令

pushq S:栈指针减少8(指针大小),将四字压入栈

等价于:

subq $8, %rsp
movq %rbx, (%rsp)

popq D:栈指针加8,将四字弹出

等价于:

movq (%rsp), %rax
addq $8, %rsp

算术操作

指令格式说明
leaqleaq S, DD <- &S,把S的地址传送给D
INCINC DD <- D+1,加1
DECDEC DD <- D-1,减1
NEGNEG D取负
NOTNOT D取补
ADDADD S, DD <- D+S,加
SUBSUB S, DD <- D-S,减
IMULIMUL S, DD <- D*S,乘
XORXOR S, D异或
OROR S, D
ANDAND S, D
SALSAL S, DD <- D<<k,左移
SHLSHL S, D左移(同SAL)
SARSAR S, D算术右移
SHRSHR S, D逻辑右移

leaq 指令

leaq(Load Effective Address)是movq指令的变形,它将有效地址写入到目的操作数,是从内存读数据到寄存器。

示例:设%rdx中值为x

leaq 7(%rdx,%rdx,4), %rax
# 将%rax中的值设置为5x+7
long scale(long x, long y, long z) {
    long t = x + 4*y + 12*z;
}

3.9.1 例题

例题3.46

3.1 寻址模式

表达式说明
%rax0x100寄存器
0x1040xAB内存地址
$0x1080x108立即数
(%rax)0xFF间接寻址
4(%rax)0x103基址+偏移
9(%rcx,%rdx)0x10c基址+变址+偏移
260(%rcx,%rdx)0x108基址+变址+偏移
0xFC(,%rcx,4)0x101变址寻址
(%rax,%rdx,4)0x118变址寻址

3.5 函数调用

函数原型:void decode1(long *xp, long *yp, long *zp)

参数传递:

  • xp in %rdi
  • yp in %rsi
  • zp in %rdx
long xp1 = *xp;
long yp1 = *yp;
long zp1 = *zp;
*yp = xp1;
*zp = yp1;
*xp = zp1;

3.6