1. 程式人生 > >80386處理器的定址方式

80386處理器的定址方式

        在實式模式下,80386處理器的最大定址空間仍然為1M,和8086/8088相似。即段地址*10H+段內偏移地址,從而形成20位地址。此種模式下,段基址是16的倍數,長度最大不超過64K。
       在保護模式下,80386處理器可以使用所有的實體記憶體。段基址可以是32位,也可以不是16的倍數,同時它的最大長度為4G,這與8086完全不同,在形成邏輯地址時用段基址直接加上段內偏移地址,而並不將段基址左移4位(乘以16)。通常情況下,除了訪問堆疊外,預設的段都為DS,有跨段字首就另當別論了。在以BP,EBP,ESP作為基址暫存器時,這時預設的段暫存器應該是SS,舉幾個簡單的例子:
     MOV EAX,[SI]; 這裡的段暫存器是DS
     MOV EAX,FS:[ESI]; 這裡的段暫存器是FS,因為指令中使用跨段字首顯示指定了
     MOV EAX,[BP]; 這裡的段暫存器是SS,因為指令中使用了BP作為基址暫存器
     MOV EAX,GS:[BP]; 這裡段暫存器是GS,因為指令中使用跨段字首顯示指定了
     80386中32位數的操作的順序是“高高低低”,即是說高16-》高16,高8-》高8,低16-》低16,低8-》低8,這和8086相似。同時80386微處理器相容所有8086的定址方式,而且對8086的定址方式有很大的改進和擴充套件。在8086下,只允許BP,BX,SI,DI作為定址暫存器,但在80386下,8個通用暫存器都可以作為定址暫存器。不過有一點要注意的是在基址變址暫存器定址方式或相對基址變址定址方式中,段暫存器由基址暫存器來確定,而不是由變址暫存器來確定,同時除ESP外其它的7個通用暫存器都可以作為變址暫存器,用程式碼來表示就是:
     MOV EAX,[EBP+ESP+2]; 這條指令是錯誤的,因為不可以用ESP作為變址暫存器
     MOV EAX,[EBP+ESI+10H]; 這裡的段暫存器應該有基址暫存器來決定。基址暫存器是BP,那麼這裡的段寄存就是SS
     MOV EAX,GS:[EBP+EDI+100H];不用看了,這裡的段暫存器應該是GS,因為指令通過跨段字首顯示指定了
     80386支援的基地址+變址+位移量定址進一步滿足了高階語言支援的資料型別。對於C語言來講,普通變數,陣列,結構體,結構體的陣列,陣列的構體我們既可存放在棧中(靜態定義-static definition),也可以存放在堆中(動態定義-dynamic definition),用ASM也一樣可以實現。基址變址暫存器提供了兩個可以改變的部分,而位移量則是靜態的。看下面的例子:
     //Variables in C Programming-Language,the corresponding ASM will list below
     void main()
     {
       int a;//普通的變數,用ASM定址時直接用DS:[一位移量],如DS:[2000],屬於直接定址方式
       int array[24];//陣列,用ASM定址時用DS:[BX+SI*4],4表示整型的長度,屬於基址變址定址方式
       struct abc
       {
         int a,b,c;
         float d;
       };
       struct abc aa;//結構體,用ASM定址時DS:[BX+Shift],Shift代表位移量,屬於暫存器相對定址方式
       struct abc aa[100];//結構體陣列,用ASM定址時用DS:[BX+SI*sizeof(abc)+Shift],屬於相對基址變址定址方式
       struct cde
       {
         int array[100];
         float e,f,g;
       };
       struct cde ccc;//陣列結構體,用ASM定址時用DS:[BX+SI*4+Shift],屬於相對基址變址定址方式
     }
     80386與8086的定址方式差不多完全一樣,只不過80386的定址方式更靈活,它的運算元有32位,16位,8位。
     讓我們再重溫一下8086的定址方式:
     a. 立即定址,所謂立即定址就是運算元就在指令中,比如說:MOV AX,5678H
     b. 直接定址,即直接包含運算元的有效地址EA,比如說MOV AX,[1234]
     c. 暫存器間址定址,用暫存器的內容來作為運算元的有效地址,比如說SI=1234,MOV AX,[SI],8086下可用的暫存器只有4個:BX,BP,SI,DI,80386下8個通用的暫存器都可以使用。
     d. 暫存器相對定址,即在暫存器間址定址方式的基礎上再加一個位移量,位移量可以是8位也可以是16位,比如說MOV AX,[BX+90H]。
     e. 基址變址定址,即運算元的有效地址由一基址暫存器和一變址暫存器產生,如MOV AX,[BX+SI]。那麼在8086下,只有SI,DI可以作為變址暫存器,在80386下除ESP外的其它7個通用暫存器都可以作為變址暫存器,比如說MOV AX,[BX+SI]。
     f. 相對基址變址定址,在e定址方式的基礎上加上一位移量,比如說MOV AX,[BX+SI+100H]。
     在8086下,我們如進行位元組或字操作,往往要加上偽指令WORD PTR或BYTE PTR。在80386下不用顯示指定,處理器會自動處理,當發現目的操作為8位時,處理器就會進行8位操作,同理當發現目的操作為16位,處理器就會進行16位操作,80386下以目的運算元的長度為準,以下幾條簡單的傳送指令:
     MOV AL,CS:[EAX]; 8位操作,段暫存器是CS,定址方式是暫存器間址定址
     MOV AL,ES:[BX]; 8位操作,段暫存器是ES,定址方式是暫存器間址定址
     MOV EDX,[EDX+EBX+1234H]; 32位操作,段暫存器是DS,定址方式是相對基址變址定址
     MOV AX,[EBX+ESI*4]; 16位操作,段暫存器是DS,定址方式是基址變址定址
     MOV BH,ES:[EBX+EDI+900H]; 8位操作,段暫存器是ES,定址方式是相對基址變址定址
     MOV DL,[EBP+ESI+1900H]; 8位操作,段寄存是SS,因為用了EBP作為基址暫存器。定址方式是相對基址變址定址