程序的机器级表示
- x86-64 汇编(AT&T 语法)
- 数据类型
- 整数按照长度分类:
- 1 字节:
b - 2 字节:字,
w - 4 字节:双字,
l - 8 字节:四字,
q
- 1 字节:
- 浮点数按照长度分类:
- 4 字节:单精度
- 8 字节:双精度
- 10 字节
- 整数按照长度分类:
- 通用寄存器
- 命名规则:
- 用前缀来区分寄存器的不同长度:
- 无前缀:16 位
e:32 位r:64 位
- 用后缀来区分寄存器中的不同部分:
l:低 8 位(仅a、b、c、d16 位寄存器)h:高 8 位(仅a、b、c、d16 位寄存器)d:低 32 位(仅%r8~%r15)- 其他: 所有部分
- 用前缀来区分寄存器的不同长度:
- 通用寄存器名称及作用:
%rax:累加结果%rbx:基址%rcx:计数器%rdx:数据%rsi:源索引%rdi:目标索引%rsp:栈指针%rbp:基址指针%r8~%r15:64 位通用寄存器,没有特殊意义
- 命名规则:
- 指令
- 操作数与寻址
- 多种形式(适用于所有指令):
- 立即数:相当于常量,硬编码在指令中,以
$开头。 - 寄存器
- 内存:用
()表示一个内存单元,括号中间是内存地址。
- 立即数:相当于常量,硬编码在指令中,以
- 内存寻址方式:
- 通用地址计算形式:
<C>(<Rb>, <Ri>, <S>),表示地址<C> + <Rb> + <S> * <Ri> - 简单寻址:
(<Rb>) - 变址:
<C>(<Rb>)
- 通用地址计算形式:
- 多种形式(适用于所有指令):
- 移动
mov?- 语法
mov? <S>, <D>,其中?可以是b、w、l、q,表示把<S>的值赋值给<D>。 - 操作数规则:
<S>、<D>是操作数,可以是立即数、寄存器、内存。- 立即数只表示 32 位有符号整数。
<S>、<D>不可以同时是内存位置。
<D>为寄存器时的赋值规则:- 如果
?是b或w,则只修改<D>的指定的位置和长度。 - 如果
?是l,则用<S>修改D的低 32 位,同时用0清空高 32 位。 - 如果
?是q,则使用全部寄存器空间,没有特殊情况。
- 如果
- 语法
movabsq- 语法
movabsq <S>, <D>,表示移动立即数。 <S>是一个 64 位立即数,其他功能与mov?类似。
- 语法
movz??- 语法
movz?? <S>, <D>,其中?都可以是b、w、l、q,表示赋值的时候清零高位(零扩展)。 - 两个
?需要满足<D>的比<S>更长。??不能是lq,因为这个是movl的默认行为。
- 语法
movs??- 语法
movz?? <S>, <D>,表示赋值的时候使用符号扩展。 - 其他与
movz??类似,但是存在movslq。
- 语法
c?t?- 语法
c?t?,表示对%ax类寄存器符号扩展再赋值给自身。 cltq表示符号扩展%eax,赋值给%rax。cqto表示符号扩展%rax,赋值给%rdx:%rax,即结果的高位在%rdx。
- 语法
- 算术/逻辑运算
leaq- 语法
leaq <C>(<Rb>, <Ri>, <S>), <D>,表示计算地址并赋值给<D>。 - 寻址计算可以用于表示乘和加,比分开的乘和加更高效。
- 语法
- 双目算术/逻辑指令
add? <S>, <D>,表示<D> += <S>。sub? <S>, <D>,表示<D> -= <S>。- 乘法系列:
imul? <S>, <D>,表示补码<D> *= <S>。imulq <S>,表示补码%rdx:%rax = <S> * %rax。mul? <S>, <D>,表示无符号<D> *= <S>。mulq <S>,表示无符号%rdx:%rax = <S> * %rax。
- 除法系列:
idivq <S>,表示补码%rax = %rdx:%rax / <S>,%rdx = %rdx:%rax % <S>。divq <S>,表示无符号%rax = %rdx:%rax / <S>,%rdx = %rdx:%rax % <S>。
and? <S>, <D>,表示<D> &= <S>。or? <S>, <D>,表示<D> |= <S>。xor? <S>, <D>,表示<D> ^= <S>。sal? <S>, <D>,表示<D> <<= <S>。sar? <S>, <D>,表示<D> >>= <S>,即算术右移。shr? <S>, <D>,表示<D> >>>= <S>,即逻辑右移。
- 单目算术/逻辑指令
neg? <D>,表示<D> = -<D>。not? <D>,表示<D> = ~<D>。inc? <D>,表示<D> += 1。dec? <D>,表示<D> -= 1。
- 操作数与寻址
- 数据类型