計算機系統-尋址

閱讀本筆記之前確保已經瞭解了CPU指令的概念
尋址包含兩種,指令尋址和操作數尋址,相對來說,任何CPU,指令尋址都要比操作數尋址簡單,注意,以下討論中以80x86爲例,並且討論中不包括四地址這種情況

一.指令尋址

1.1順序尋址
這是最基本的尋址方式,當一條指令執行完畢之後,程序計數器(PC)自動增加,於是就形成了下一條指令的地址,這樣CPU就可以順序的執行下一條指令地址了

1.2跳躍尋址

1.2.1無條件跳躍尋址
C語言中的goto就是跳躍尋址,說白了就是不需要任何條件,直接跳轉到其他分支

int main()
{
	printf("A");
	goto C;
	printf("B");
	C:
	printf("C");
}

這段代碼就是執行了跳躍尋址,正常情況下應該打印出“B”的,但是由於goto關鍵詞的存在,所以跳過了B,直接打印出了C,下面是上述C代碼的反彙編代碼片段,我們可以看到jmp指令就是跳躍指令

000718A3  call        @__CheckForDebuggerJustMyCode@4 (071217h)  
	printf("A\n");
000718A8  push        offset string "A\n" (077B30h)  
000718AD  call        _printf (07104Bh)  
000718B2  add         esp,4  
	goto C;
000718B5  jmp         C (0718C6h)  //表示跳轉到0718C6地址執行
000718B7  jmp         C (0718C6h)  //表示跳轉到0718C6地址執行
	printf("B\n");
000718B9  push        offset string "B\n" (077BD0h)  
000718BE  call        _printf (07104Bh)  
000718C3  add         esp,4  
	C:
	printf("C\n");
// 會跳轉到這裏執行代碼
000718C6  push        offset string "C\n" (077BD4h)  
000718CB  call        _printf (07104Bh)  
000718D0  add         esp,4 

1.2.2有條件跳躍尋址
很多高級語言都有if關鍵字,if就是有條件跳躍尋址,比如下面的代碼

int main()
{
	int a = 3;
	if (a==0) {
		a == 1;
	}
}

彙編指令如下

	int a = 3;
00B917B8  mov         dword ptr [a],3  
	if (a==0) {
00B917BF  cmp         dword ptr [a],0  // 注意此處cmp操作ZF標誌位
00B917C3  jne         main+3Ch (0B917CCh)  
		a = 1;
00B917C5  mov         dword ptr [a],1  
	}
}

上述代碼首先,if(a==0)會執行cmp操作,用a減0,將結果存放到ZF標誌位中,然後下一條指令去讀取ZF標誌位,由ZF標誌位決定是否跳轉,而不是CPU判斷a是否等於0,來決定跳轉,切記
我們可以簡單的理解成,無論a是否==於0,都會進入到if裏,至於是否再繼續執行,則是CPU去判斷ZF標誌位來決定的了

下面介紹if,else語句,很有意義,希望仔細閱讀

int main()
{
	int a = 3;
	if (a==0) {
		a = 1;
	}
	else {
		a = 2;
	}
}

其對應的彙編如下

	int a = 3;
00BD17B8  mov         dword ptr [a],3  
	if (a==0) {
00BD17BF  cmp         dword ptr [a],0  
00BD17C3  jne         main+3Eh (0BD17CEh)  
		a = 1;
00BD17C5  mov         dword ptr [a],1  
	}
	else {
00BD17CC  jmp         main+45h (0BD17D5h)  
		a = 2;
00BD17CE  mov         dword ptr [a],2  
	}
0BD17D5

首先執行cmp命令,將比較結果存到ZF,如果CPU判斷ZF爲1則相等,那麼jne指令則無法滿足,則不跳轉,執行代碼a=1,執行完代碼a=1之後,你以爲不進入else了????其實代碼會進入到else的,但是,else裏面的第一條指令就是jmp,直接跳轉到0BD17D5位置了,也就是說沒有執行else裏的其他代碼

如果CPU根據ZF標誌位加上一些其他標誌位判斷出a不等於0,則觸發jne這個跳轉命令,跳轉到0BD17CE位置,這個位置就是執行了mov操作,也就是代碼裏的a=2

循環語句也會導致有條件跳躍尋址

還有一個我們大家每天都在用的,函數調用(方法調用),也會導致有條件跳躍尋址,博客裏就不寫了,內容太多也不愛看,他們的本質都是與if相同的

二.操作數尋址

2.1立即尋址
操作數裏面裝的內容就是該值本身,比如代碼

a=1+2

那麼操作數尋址就是add 1 2,當然,add是我臆想出來的指令,不過只是舉例,就是說,add後面接的兩個操作數,是1和2兩個值本身
2.2直接尋址
還是上述代碼a=1+2
那麼直接尋址就是add 0x1234 0x5678,然後再通過0x1234找到值1,通過0x5678找到值2,之後再相加
2.3間接尋址
還是上述代碼a=1+2
簡介尋址就是add 0x1234 0x5678,然後通過0x1234找到值0x4444(注意此處是根據地址又找到了一個地址,理論上可以無限往復循環找地址),然後在根據0x4444繼續往下找,一直找到真正的值1,這就叫間接尋址
2.4寄存器尋址
只的是操作數裏裝的是地址,但是這個地址不是主存的地址,而是某個寄存器的地址
寄存器直接尋址:假設有個操作是op a,表示對a進行op操作,那麼這a其實是某個寄存器的地址,通過a,在某個寄存器中找到a真正的值
寄存器間接尋址:假設有個操作是op a,表示對a進行op操作,那麼這a其實是某個寄存器的地址,通過a,在某個寄存器中找到a在主存中的地址,然後在根據這個主存中的地址,去主存中拿到a真正的值
2.5偏移尋址
對於偏移尋址,此處我不太明白,待以後再研究吧
偏移尋址包括相對尋址,基址寄存器尋址,變址尋址;
相對尋址:經常被用在跳轉指令中,跳轉後的目標地址與當前地址有一定的距離,這個距離就叫做相對偏移量。
基址寄存器尋址:
變址尋址:
2.6堆棧尋址
現代計算機完成函數調用時所使用的尋址方式
首先計算機必須提供堆棧結構,堆棧結構是現代數據結構中的一個概念,堆棧可以使用寄存器來實現,這叫做硬堆棧,堆棧也可是使用主存來實現,這叫做軟堆棧,它是一種先進後出的讀數讀寫順序模型

代碼揭祕P181

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