CPU 提供了什麼

爲了方便理解,CPU 能夠簡單認爲是:架構

  1. 一堆的寄存器,用於暫時存放數據
  2. 能夠執行機器指令,完成運算 / 數據讀寫 等操做

寄存器

CPU 有不少的寄存器,這裏咱們只介紹 指令寄存器 和 通用寄存器。函數

指令寄存器

64 位下,指令寄存器叫 rip (32 位下叫 eip)。
指令寄存器用於存放下一條指令的地址,CPU 的工做模式,就是從 rip 指向的內存地址取一條指令,而後執行這條指令,同時 rip 指向下一條指令,如此循環,就是 CPU 的基本工做。指針

也就意味着,一般模式下 CPU 是按照順序執行指令的。可是,CPU 也有一些特殊的指令,用於直接修改 rip 的地址。好比,jmp 0xff00 指令,就是把 rip 改成 0xff00,讓 CPU 接下來執行內存中 0xff00 這個位置的指令。code

通用寄存器

以 x86_64 來講,有 16 個「通用」寄存器。「通用」意味着能夠聽任意的數據,這 16 個寄存器並無什麼區別,可是實際上仍是存在一些約定俗稱的用法:ip

先看看這 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

注意:由於棧在內存空間中是倒過來的,因此是向下生長的。

相關文章
相關標籤/搜索