关于asm:CPU-提供了什么

38次阅读

共计 1560 个字符,预计需要花费 4 分钟才能阅读完成。

为了不便了解,CPU 能够简略认为是:

  1. 一堆的寄存器,用于临时存放数据
  2. 能够执行机器指令,实现运算 / 数据读写 等操作

寄存器

CPU 有很多的寄存器,这里咱们只介绍 指令寄存器 和 通用寄存器。

指令寄存器

64 位下,指令寄存器叫 rip(32 位下叫 eip)。
指令寄存器用于寄存下一条指令的地址,CPU 的工作模式,就是从 rip 指向的内存地址取一条指令,而后执行这条指令,同时 rip 指向下一条指令,如此循环,就是 CPU 的根本工作。

也就意味着,通常模式下 CPU 是依照程序执行指令的。然而,CPU 也有一些非凡的指令,用于间接批改 rip 的地址。比方,jmp 0xff00 指令,就是把 rip 改为 0xff00,让 CPU 接下来执行内存中 0xff00 这个地位的指令。

通用寄存器

以 x86_64 来说,有 16 个“通用”寄存器。“通用”意味着能够放任意的数据,这 16 个寄存器并没有什么区别,然而实际上还是存在一些约定俗称的用法:

先看看这 8 个:
(这是原来 32 位架构下就有的,只是 32 位下是 e 结尾的)

rax: "累加器"(accumulator), 很多加法乘法指令的缺省寄存器,函数返回值个别也放在这里
rbx: "基地址"(base)寄存器, 在内存寻址时寄存基地址
rcx: 计数器 (counter), 是反复(REP) 前缀指令和 LOOP 指令的内定计数器
rdx: 用来放整数除法产生的余数,或者读写 I / O 端口时,用来寄存端口号
rsp: 栈顶指针,指向栈的顶部
rbp: 栈底指针,指向栈的底部,通常用 `rbp+ 偏移量 ` 的模式来定位函数寄存在栈中的局部变量
rsi: 字符串操作时,用于存放数据源的地址
rdi: 字符串操作时,用于寄存目标地址的,和 rsi 常常搭配一起应用,执行字符串的复制等操作

另外还有 8 个,是 64 位架构下新增的:

r8, r9, r10, r11, r12, r13, r14, r15

机器指令

在 CPU 的世界里,只有 0 1 这种二进制的示意,所以指令也是用 0 1 二进制示意的。
然而,二进制对人类并不敌对,所以有了汇编这种助记符。

算术运算

比方这段加法:

add    rax,rdx

比方这个汇编指令,示意:rax = rax + rdx,这就实现了一个加法的运算。
通常咱们用 rax 寄存器来做加法运算,然而其余寄存器一样也能够实现加法运算的,比方:

add    rbx,0x1

这个示意 rbx = rbx + 0x1

这里的加法运算,都是在寄存器上实现的,也就是间接批改的寄存器的值。

跳转指令

比方这段无条件跳转指令

jmp 0x269e001c

CPU 默认是依照程序执行指令的,跳转指令则是,让 CPU 不再程序执行后续的指令,转而执行 0x269e001c 这个内存地址中的指令。
具体来说,将指令寄存器中的值改为 0x269e001c 即可,即:rip = 0x269e001c

内存读写指令

比方这一对 mov 指令:

mov rbp, [rcx]
mov [rcx], rbp

这里假如 rcx 的值,是一个内存地址,比方:0xff00
第一行 mov 指令,是将内存地址 0xff00 中的值,读取到 rbp 寄存器。
第二行 mov 指令,则是反过来,将 rbp 寄存器的值,写入到内存 0xff00 中。

栈操作

pushpop 这一对用于操作“栈”。
“栈”是内存空间中的一段地址,咱们约定是以栈的模式来应用它,并且用 rsp 寄存器指向栈顶。

栈操作实质也是内存读写操作,只是以栈的形式来应用。

比方这一对:

push   rbp
pop    rbp

第一行是将 rbp 寄存器中的值压入栈,等效于:

sub rsp, 8       // rsp = rsp - 8; 栈顶向下成长 8 byte
mov [rsp], rbp   // rbp 的值写入新的栈顶

第二行则是反过来,栈顶弹出一个值,写入到 rbp 寄存器中,等效于:

mov rbp, [rsp]   // 栈顶的值写入 rbp
add rsp, 8       // rsp = rsp + 8; 栈顶向上放大 8 byte

留神:因为栈在内存空间中是倒过去的,所以是向下成长的。

正文完
 0