linux內核源碼分析(一)X86彙編指令

目錄

 

什麼是馮諾伊曼體系?

X86寄存器

彙編指令

mov指令

mov指令的長度分類

mov指令的操作數

mov的操作數組合

基本的內存尋址模型

pushl/popl/call/ret

C語言反編譯


什麼是馮諾伊曼體系?

可以看到馮諾依曼架構不區分數據與指令,將兩者放在同一內存中;而哈佛結構將兩者分別存放在Instruction Memory和Data Memory。
指令和數據放在一起的後果是取指令和取數據不能同時進行,否則會引起訪存的混亂。發展到今天,CPU的運算速度已經遠遠超過了訪存速度,因此CPU必須浪費時間等數據;而哈佛構架由於指令和數據是分開存放的,所以在等數據的同時可以預取指令,CPU的利用率更高。

由於指令與數據放在同一內存帶來的CPU利用率(吞吐率)限制就是馮諾依曼瓶頸。

馮諾依曼瓶頸的緩解辦法有:

Providing a cache between the CPU and the main memory
providing separate caches or separate access paths for data and instructions (the so-called Modified Harvard architecture)
using branch predictor algorithms and logic
providing a limited CPU stack or other on-chip scratchpad memory to reduce memory access

X86寄存器

彙編指令

參考:https://www.jianshu.com/p/fd1cfed8a2d2

mov指令

介紹:在彙編中mov指令主要用於在主內存(RAM)和寄存器之間傳輸數據,按照傳遞的方向可以分爲兩類

  • 加載(Load)指令:從主內存(RAM)寄存器傳輸數據,以一個給定的內存地址作爲參數,他從內存中獲取該地址位置存儲的數據,並將該數據放入寄存器
  • 存儲(Store)指令:即從寄存器中緩存的內存地址中所指向的目標位置,並將另外一個寄存器中緩存的數據保存到該目標位置,我們可以把內存看作已經編了號的數組,而通過索引就是內存地址,通過指定的內存地址可以在特定位置中的修改內存中的數據。

mov指令的長度分類

根據操作數的字長可以分爲三個版本的mov指令

  • movl Source Dest : L表示可以移動4個字節
  • movw Source Dest: W表示可以移動2個字節
  • movb Source Dest: B表示可以移動1個字節

mov指令的操作數

並且在移動指令中會用到兩個操作數,Source表示移動的數據源,Dest表示移動的數據最後到達的位置。
通常在x86用的比較頻繁的mov指令版本是32位的movl,這裏就以 movl Source Dest爲例子

mov指令的操作數通常分爲三類

  • 立即數(Immediate) 可以將其視爲常數,和C語言的常量類似,但是以“$”爲前綴,例如0x400,-500
  • 寄存器(Register)可以是以上8個整數寄存器中的其中一個,例如:“%eax”,“%edx”,當我們執行類似“movl %eax %edx”這種情況下,eax寄存器就成爲源參數,而edx寄存器就成爲目標參數,其含義是獲取eax中的內容並存儲在edx中。
  • 內存(Memory):而內存作爲操作數通常是由寄存器緩存給定的內存地址來間接去操作的,該地址佔用4個字節,例如(%eax),當寄存器在一個括號中,我們就說eax持有一個指向RAM中的某個位置的地址,你可以類比爲類似C/C++中的指針變量,的那麼 movl (%eax) %ebx 表示的是什麼意思呢?你可以考慮一下表示什麼意思?

mov的操作數組合

movl指令通過不同類型的操作數組合,能夠表達出不同類型的指令類型的。

基本的內存尋址模型

間接訪問
就是“(R)”這種格式,R表示一個寄存器名稱。寄存器中保存着一個內存地址,我們用mov指令操作主內存時,只能通過使用該寄存器中的內容去實現對該地址指向的RAM中位置進行讀/寫操作。對於操作系統來說,內存其實就是一個連續的字節數組,每個字節都有對應的編號,而這個編號就是內存地址,也可以理解爲該字節數組的索引。

我們用“RAM”表示主內存,那麼 (R) 其實等價於 RAM[Reg[R]],

那麼“movl (%edx),%eax”類似這樣的指令的含義到這裏應該不用多說了吧!

移位尋址
英文名稱叫“Displacement”,這個其實就是在間接尋址表達式的基礎是加上一個有符號的整數N。在彙編中抽象的移位尋址表達式“N(R)

我們用“RAM”表示主內存,那麼 N(R) 其實等價於 RAM[Reg[R]+N],

那麼具體的例子就是

  • 例如 “-4(%ebp)”:表示ebp寄存器中緩存的內存地址向低地址方向移動了4個字節
  • 例如“8(%ebp)”:表示ebp寄存器中緩存的內存地址向高地址方向移動8個字節。
  • 那麼像這種“movl 4(%esp),%ecx”其實就是寄存器esp的指針向高地址方向偏移4個字節後的個新的地址,從該新地址指向的內存位置獲取數據並保存到寄存器ecx。

pushl/popl/call/ret

參考:https://blog.csdn.net/striver1205/article/details/25695437

 

C語言反編譯

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章