?? 匯編005.txt
字號:
80386實模式下編程
80386在實模式下是一個更快的8086,它不但可以進行32位操作,而且還可以進32位尋址,并且還可以使用80386的擴展指令。不過,由于是在實模下,尋址的最大空間為1M。在一個段內,段的最大長度不超過64K,否則就會發生異常。
在8086下定義一個段的完整格式是:
段名 [定位類型] [組合類型] [‘類別’]
80386下定義一個段的完整格式是:
段名 [定位類型] [組合類型] [‘類別’] [屬性類型]
說明:屬性類型有兩種:USE32和USE16,USE32表示32位段,USE16表示16位段。如果你在程序中用到偽指令.386,那么默認的屬性類型就是USE32(32位段),如果沒有用偽指令指定CPU的類型,那么默認的屬性類型就是USE16,在實方式下只能使用16位段,即用USE16。
eg:
CSEG PARA PUBLIC USE32;定義一個32位的段
AA DW ?
BB DD ?
CC DB ?
DD DW ?
EE DW 0,0,0.....
CSEG ENDS
由于在80386中用到了66H操作前綴和67H地址前綴,因此盡管在實式模式下,只要設定的CPU類型是80386,仍然可以進行32位操作,可以進行32位尋址,66H,67H這兩個前綴無需程序員在程序中書寫,匯編程序會自動加上的。只要在程序中對32位操作數進行訪問,或進行32位尋址,那么就會加上操作數前綴66H和地址前綴67H。相反,如果在32位段中對16位或8位的訪問,匯編程序中也會加上這兩個前綴。
下面將給出一個例子程序,演示一下在80386的實模式下編程的方法與技巧(這是從網上down的一個程序,不是我寫的,但我會作詳細的解剖,并與8086下的程序設計作出比較):
用十進制,十六進制,二進制三種形式顯示雙字存儲單元F000:1234中的內容
|------------------MAIN PROC------------|
| .386 |
| code segment para public 'code' use16 |
| assume cs:code |
| begin: |
| mov ax,0f000h |
| mov fs,ax |
| mov eax,fs:[1234H] |
| call todec |
| call newline |
| call tohex |
| mov al,'H' |
| call echo |
| call newline |
| call tobin |
| mov al,'B' |
| call echo |
| call newline |
| mov ah,4ch |
| int 21h |
|---------------------------------------|
;sub-function todec
todec proc near
pushad
mov ebx,10
xor cx,cx
dec1:
xor edx,edx
div ebx
push dx
inc cx
or eax,eax
jnz dec1
dec2:
pop ax
call toasc
call echo
loop dec2
popad
ret
todec endp
;sub-function tobin
tobin proc near
push eax
push ecx
push edx
bsr edx,eax
jnz bin1
xor dx,dx
bin1:
mov cl,31
sub cl,dl
shl eax,cl
mov cx,dx
inc cx
mov edx,eax
bin2:
rol edx,1
mov al,'0'
adc al,0
call echo
loop bin2
pop edx
pop ecx
pop eax
ret
tobin endp
;sub-function tohex
tohex proc near
countb=8
enter countb,0
movzx ebp,bp
mov ecx,countb
mov edx,eax
hex1:
mov al,dl
and al,0fh
mov [ebp-countb+ecx-1],al
ror edx,4
loop hex1
mov cx,countb
xor ebx,ebx
hex2:
cmp byte ptr [ebp-countb+ebx],0
jnz hex3
inc ebx
loop hex2
dec ebx
mov cx,1
hex3:
mov al,[ebp-countb+ebx]
inc ebx
call toasc
call echo
loop hex3
leave
ret
tohex endp
;sub-function toasc
toasc proc near
and al,0fh
cmp al,'0'
cmp al,'9'
seta dl
movzx dx,dl
imul dx,7
add al,dl
toasc1:ret
toasc endp
;sub-function newline
newline proc near
push dx
push ax
mov dl,0dh
mov ah,2
int 21
mov dl,0ah
int 21
pop ax
pop dx
ret
newline endp
echo proc near
push ax
push dx
mov dl,al
mov ah,2
int 21h
pop dx
pop ax
echo endp
剖析:
先來看主程序框架,下面就是MAIN PROC:
|------------------MAIN PROC-------------------------------|
|.386;定義處理器的類型為386表示可以使用所有80386指令 |
| code segment para public 'code' use16 |
| assume cs:code |
| begin: |
| mov ax,0f000h |
| mov fs,ax;將f000h裝入段寄存器fs |
| mov eax,fs:[1234H];將1234H內存單元中的雙字送給寄存器EAX|
| call todec;調用子過程todec |
| call newline;調用子過程newline進行回車換行 |
| mov eax,fs:[1234h]; |
| call tohex;調用子過程tohex |
| mov al,'H' |
| call echo;顯示字符H |
| call newline; |
| mov eax,fs:[1234H] |
| call tobin;調用子過程tobin |
| mov al,'B' |
| call echo
| call newline |
| mov ah,4ch |
| int 21h |
|----------------------------------------------------------|
主程序中的內容一目了然,很簡單。和8086下唯一不同的是就是要用偽指令定義CPU的類型,并且段寄存器的定義多了一個屬性類型USE16,再就是32位操作,使用80386的指令,其它的和8086下沒有什么區別。
重點是要分析幾個過程,從網上down下來時,過程newline和toasc沒有實現代碼,因為這很簡單,所以上述toasc,newline,echo的過程體是由我寫進去的,這兩個過程體代碼不多而且非常簡單,就不作介紹了。重點介紹todec,tobin,tohex。
a.子過程todec,這個子過程的主要功能是將f000:1234雙字單元的內容用十進制顯示,下面就來看每一行代碼:
|-----------------------------------------------------------|
|todec proc near |
| pushad |
| mov ebx,10 |
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -