Posted on 2016-04-10 23:56
eryar 閱讀(1659)
評論(1) 編輯 收藏 引用
CPU Instruction Pointer
eryar@163.com
1.Introduction
CPU對存儲器的讀寫通過總線Bus來完成,總線又分為地址總線(Address Bus)、數據總線(Data Bus)、控制總線(Control Bus)。地址總線AB決定了CPU的尋址能力,即可以訪問的存儲空間的大小。數據總線DB決定了CPU的一次操作中可以處理的數據的大小,16位CPU一次可以加載兩個字節,32位CPU一次可以加載4個字節。當然CPU的主頻越大,那么在相同的時間內,處理的次數會更多。
2.16bit CPU
由于8086CPU有20位地址總線,所以尋址能力為1MB。但是8086所有的寄存器都是16位的,如果由寄存器直接處理地址,那么一個16位的寄存器可以訪問的最大地址為64KB。如何通過16位的寄存器來訪問這1MB的空間呢?8086CPU折騰出一個地址加法器,通過加法器來根據兩個16位地址來合成一個20位的地址,即物理地址=段地址X16+偏移地址。對應到CPU中就是CS和IP這兩個寄存器。
8086CPU中的CS和IP的內容提供了CPU要執行指令的地址。在CPU中,程序員能夠用指令讀寫的部件只有寄存器,程序員可以通過改變寄存器中的內容實現對CPU的控制。CPU從何處執行指令是由CS和IP中的內容決定的,程序員可以通過改變CS和IP中的內容來控制CPU執行目標指令。
若想同時修改CS和IP的內容,可以用形如jmp 段地址:偏移地址的指令完成。如下圖所示:
3.32bit CPU
因為80386的CPU尋址能力是4GB,所以它的尋址模式是平坦模式,不需要用段地址+偏移地址來折騰。所以32位CPU的EIP寄存器對應了16位CPU中的CS和IP兩個寄存器。修改了EIP寄存器就可以改變CPU要執行的指令。如下面一段簡單代碼:
#include <stdio.h>
int main(int argc, char* argv[])
{
mark: printf("hi
\n");
goto mark;
return 0;
}
使用了goto,在Debug時可以在Visual Studio中看到CPU中相關寄存器中的信息如下圖所示:
由上圖可知,goto對應的匯編命令就是一個修改EIP寄存器的jmp指令。