汇编指令和寄存器

寄存器

早期的 x86 CPU 只有 8 个寄存器(eaxebxecxedxesiediebpesp),而且每个都有不同的用途。

寄存器名称 含义 用途 包含寄存器
eax 累加(Accumulator)寄存器 常用于乘除法和函数返回值 axahal
ebx 基址(Base)寄存器 常以它为基址来访问内存 bxbhbl
ecx 计数器(Counter)寄存器 常做字符串和循环操作中的计数器 cxchcl
edx 数据(Data)寄存器 常用于乘除法和 I/O 指针 dxdhdl
esi 来源索引(Source Index)寄存器 常用于内存数据指针和源字符串指针 si
edi 目的索引(Destination Index)寄存器 常用于内存数据指针和源字符串指针 di
ebp 基址指针(Base Pointer)寄存器 只做堆栈指针,可以访问堆栈内任意地址,经常用于中转 ESP 中的数据,也常以它为基址来访问堆栈;不能用于算术运算与数据传送 bp
esp 堆栈指针(Stack Pointer)寄存器 只做堆栈的栈顶指针,不能用于算术运算与数据传送 sp

栈帧中,最重要的是帧指针 ebp 和栈指针 esp,有了这两个指针,我们就可以刻画一个完整的栈帧。

x86-64 中,所有寄存器都是 64 位,相对 32 位的 x86 来说,标识符发生了变化,比如:从原来的 eax 变成了 rax。为了向后兼容性,eax 依然可以使用,不过指向了 rax 的低 32 位。

比如在 64 位 CPU 上:

  • rax 是 64 位的寄存器
  • raxrax 的低 32 位
  • axrax 的低 16 位
  • ahax 的高 8 位。
  • alax 的低 8 位。

它们的对照关系如下:

00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
|=================================RAX=================================|---8个字节
                                    |===============EAX===============|---4个字节
                                                      |======AX=======|---2个字节
                                                      |==AH===|-----------1个字节
                                                              |===AL==|---1个字节

通过 gdb 的 p /x $reg 命令打印寄存器的值。

(gdb) p /x $rax
$16 = 0x555555554870
(gdb) p /x $eax
$12 = 0x55554870
(gdb) p /x $ax
$13 = 0x4870
(gdb) p /x $ah
$14 = 0x48
(gdb) p /x $al
$15 = 0x70

汇编指令

1. 数据传送指令

指令 名称 语法 描述
mov 数据传送指令 mov dest, src 将数据从 src 移动到 dest
push 入栈指令 push src 将源操作数 src 压入堆栈
pop 入栈指令 pop dest 从栈顶弹出数据到 dest

1.1 mov 指令

mov 指令是最常见的数据传送指令,类似于高级语言中的赋值语句。

mov 指令可以实现寄存器与寄存器之间、寄存器与内存之间、寄存器与立即数、内存与立即数的数据传递。

需要注意的是,内存与内存无法直接传递数据,目的操作数不能为立即数。

mov 指令的用法示例如下:

mov eax, 12345678h
mov eax, [00401000h]
mov eax, ebx
mov [00401000h], 12345678h
mov [00401000h], eax

1.2 pushpop 指令

push 指令和 pop 指令互为相反的操作指令。

  • push 指令的功能是将操作数压入堆栈。
  • pop 指令的功能是将栈顶的操作数弹出。

push 指令把一个 32 位的操作数送入堆栈,该操作致使 esp 寄存器的值减 4。
esp 寄存器始终指向栈顶。堆栈的方向是由高地址向低地址进行延伸,也就是执行的 push 次数越多,esp 寄存器指向的地址越小。
在 32 位平台上,每执行一次 push 指令,esp 指向的地址都减小 4 字节。

pop 指令把 esp 指向地址(栈顶)中的值送入寄存器或内存中,然后 esp 指向的地址加 4 字节。
执行的 pop 指令越多,esp 寄存器指向的地址越大。

(2)算术运算指令

指令 名称 语法 描述
add 加法指令 add dest, src dest 基础上加 src
sub 减法指令 sub dest, src dest 基础上减 src
inc 加 1 指令 inc dest dest 基础上加 1
dec 减 1 指令 dec dest dest 基础上减 1

(3)逻辑运算指令

指令 名称 语法 描述
not 取反运算指令 not dest 把操作数 dest 按位取反
and 与运算指令 and dest, src destsrc 进行与预算之后送回 dest
or 与运算指令 or dest, src destsrc 进行或预算之后送回 dest
xor 与运算指令 xor dest, src destsrc 进行异或预算之后送回 dest

(4)循环控制指令

指令 名称 语法 描述
loop 计数循环指令 loop label 使 ecx 寄存器的值减 1,当 ecx 寄存器的值不为 0 的时候跳转至 lable,否则执行 loop 之后的语句

(5)转移指令

指令 名称 语法 描述
jmp 无条件转移指令 jmp label 无条件跳转至标号为 lable 的位置
call 过程调用指令 call label 直接调用 lable
je 条件转移指令 je label zf = 1 时跳转至标号为 lable 的位置
jne 条件转移指令 jne label zf = 0 时跳转至标号为 lable 的位置

参考

  • 编译器的工作过程
  • 汇编语言入门教程
  • 汇编指令入门级整理
  • x86汇编语言之常用汇编指令
  • 函数调用栈
  • x86汇编指令(push,pop,call,ret)
  • x86-64 下函数调用及栈帧原理
  • 一口气看完45个寄存器,CPU核心技术大揭秘

你可能感兴趣的:(汇编指令和寄存器)