ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 寄存器 X86-64大约有16个64位整数寄存器,其中栈指针`rsp`和基址指针`rbp`较为特殊,`rsi`和`rdi`跟处理字符串相关。后面的八个寄存器是编号的,使用起来没有特殊限制。 * rax rbx rcx rdx * rsi rdi rbp rsp * r8 - r15 *其中rax的结构如下* `rax`的低八位为`al`,接着八位是`ah`,合并为`ax`,低32位为`eax`,整个64位是`rax`。 *R8的结构如下* 大多数编译器产品会混合使用32位和64位模式。32位用来做整数计算,64位一般用来保存内存地址(指针)。 ## 寻址模式 `mov`指令有一个决定移动多大数据的单字母前缀 * movb Byte 8bits * movw Word 16bits * movl Long 32bits * movq Quadword 64bits 对于使用AT&T语法的GAS(GNU汇编器): GAS汇编指令通常以字母“b”,“s”,“w”,“l”,“q”或“t”来确定要操作的大小操作数。 * b =字节(8位) * s =短(16位整数)或单个(32位浮点) * w =单词(16位) * l = long(32位整数或64位浮点数) * q =四(64位) * t =十个字节(80位浮点数) ## leal 和 movl区别 leal(load effective address)  S,D  -> &S -> D movl S,D -> S -> D 简单的说就是 movl是把访问的内存内容赋值给寄存器, leal是將地址赋值给寄存器 ## 栈指令 | 指令 | 效果 | 描述 | | --- | --- | --- | | pushq S | %rsp ← %rsp - 8 | 将四字压入栈 | | (%rsp) ← S | | popq D | D ← (%rsp) | 将四字弹出栈 | | %rsp ← %rsp + 8 | ### 需要注意的点 * pushq指令的行为等价于:`subq $8, %rsp` 与`movq %rbp, (%rsp)`两条指令的合效果。 * popq指令的行为等价于: `movq (%rsp), %rax` 与`addq $8, %rsp`两条指令的合效果。 * push/pop指令不存在其他后缀。 ## 算数和逻辑指令 | 指令 | 效果 | 描述 | | --- | --- | --- | | leaq S , D | D ← &S | 加载有效地址 | | inc D | D ← D + 1 | 加一 | | dec D | D ← D - 1 | 减一 | | neg D | D ← -D | 取负 | | not D | D ← ~D | 取补 | | add S , D | D ← D + S | 加 | | sub S , D | D ← D - S | 减 | | imul S , D | D ← D \* S | 乘 | | div S , D | D ← D ÷ S | 除 | | xor S , D | D ← D ^ S | 异或 | | or S , D | D ← D | S | 或 | | and S , D | D ← D & S | 与 | | sal k , D | D ← D << k | 左移 | | shl k , D | D ← D << k | 左移(等同于sal) | | sar k , D | D ← D >>(A) k | 算数右移 | | shr k , D | D ← D >>(L) k | 逻辑右移 | ## 加载有效地址 **加载有效地址**指令leaq实质上是movq指令的变形。它的指令形式是从内存读取数据到寄存器,但实际上leaq没有引用内存。他的作用是将内存地址放入操作数中。**该命令的目标必须是一个寄存器**,同时leaq可以简洁的描述算数运算,所以有时它的使用与有效地址的计算无关。例如: ``` long scale(long x, long y, long z) { long t = x + 4 * y + 12 * z; return t; } ``` ``` ; long scale(long x, long y, long z) ; x in %rdi, y in %rsi, z in %rdx scale: leaq (%rdi, %rsi, 4), %rax ; x + 4 * y leaq (%rdx, %rdx, 2), %rdx ; z + 2 * z leaq (%rax, %rdx, 4), %rax ; (x + 4 * y) + 4 * (3 * z) ``` ## 特殊的算数指令 | 指令 | 效果 | 描述 | | :-- | :-- | :-- | | imulq S | %rdx : %rax ← S × (%rax) | 有符号全乘法 | | mulq S | %rdx : %rax ← S × (%rax) | 无符号全乘法 | | clto | %rdx : %rax ← 符号扩展(%rax) | 扩展为八字 | | idivq S | %rdx ← (%rdx) : (%rax) mod S | 有符号除法 | | | %rdx ← (%rdx) : (%rax) ÷ S | | | divq S | %rdx ← (%rdx) : (%rax) mod S | 无符号除法 | | | %rdx ← (%rdx) : (%rax) ÷ S | | * %——百分号表示这是一个寄存器。 * e表示extend 意思是扩展到了32位。因为以前的intel寄存器都是16位的,它们的名字就是%ax,%bx等等,所以扩展到32位之后就在开头加上一个e,改名叫%eax,%ebx等