從今天開始,用心學習王爽的《匯編語言》!
扎扎實實,勿在浮沙建高樓!
—————2012.5.29 21:30
第1章 基礎知識
以后用到的知識,以后再說。
匯編課程的研究重點放在如何利用硬件系統的編程結構和指令集有效靈活地控制系統進行工作。
每一種微處理器,由于硬件設計和內部結構的不同,就需要用不同的電平脈沖來控制,使他工作。所以每一種微處理器都有自己的機器指令集,也就是機器語言。
匯編語言由以下3類指令組成:
匯編指令:機器碼的助記符,有對應的機器碼。
偽指令:沒有對應的機器碼,由編譯器執行,計算機并不執行。
其他符號:如:+、-、*、%等,由編譯器識別,沒有對應的機器碼。
匯編語言的核心是匯編指令,它決定了匯編語言的特性。
要靈活地利用匯編語言編程,首先要了解CPU是如何從內存中讀取信息,以及向內存中寫入信息的。
總線:
根據傳送信息的不同,總線從邏輯上又分為3類,即地址總線、控制總線和數據總線。
地址總線:
CPU是通過地址總線來指定存儲器單元的。地址總線上能傳送多少個不同的信息,CPU就可以對多少個存儲單元進行尋址。
所以32位機器,地址總線有32根,能尋址2^32=4G空間。
數據總線:
CPU與內存或其他器件之間的數據傳送是通過數據總線來進行的。數據總線的寬度決定了CPU和外界的數據傳送速度。
32位的數據總線一次能傳送4個字節的數據。
控制總線:
CPU對外部器件的控制是通過控制總線來進行的。在這里控制總線是個總稱,控制總線是一些不同控制線的集合。有多少根控制總線,就意味這CPU提供了對外部器件的多少種控制。所以,控制總線的寬度決定了CPU對外部器件的控制能力。
內存地址空間
最終運行程序的是CPU,我們用匯編編程的時候,必須要從CPU角度考慮問題。對CPU來講,系統中的所有存儲器中的存儲單元都處于一個統一的邏輯存儲器中,他的容量受CPU尋址能力的限制。這個邏輯存儲器即是我們所說的內存地址空間。
那么,80386PC的內存地址空間是如何分布的呢?
第2章 寄存器(CPU工作原理)
一、寄存器分類:
數據寄存器:AX、BX、CX、DX四個寄存器
指針寄存器:SP堆棧指針、BP基址指針
變址寄存器:SI源地址、DI目的地址
段寄存器:CS代碼段、DS數據段、SS堆棧段、ES附加段
控制寄存器:IP指令指針寄存器、FLAG標志寄存器
數據寄存器,指針寄存器和變址寄存器統稱為通用寄存器。這樣稱呼的理由是,這些寄存器除了各自規定的專門用途外,他們均可用于傳送和暫存數據,可以保存算術邏輯運算中的操作數和運算結果。
二、寄存器訪問規則:
1、兩個操作對象的位數應當是一致的。
2、8086CPU不支持直接將數據送入段寄存器的操作。
3、只有mov、push、pop指令能對段寄存器進行操作。
4、8086CPU的入棧和出棧操作都是以字為單位進行的。
5、在8086CPU中,只有bx,si,di,bp這4個寄存器可以用在[]中來進行內存單元的尋址。
6、在[]中,這4個寄存器可以單個出現,或只能以4種組合出現:bx和si、bx和di、bp和si、bp和di。
7、只要在[]中使用寄存器bp,而指令中沒有顯性的給出段地址,段地址就默認在ss中。
一個典型的CPU由運算器、控制器、寄存器等器件構成,這些器件靠內部總線相連。
8086的所有寄存器都是16位的,可以存放兩個字節。
16位結構描述了一個CPU具有下面幾方面的結構特性:
1、運算器一次最多可以處理16位的數據。
2、寄存器的最大寬度為16位。
3、寄存器和運算器之間的通路為16位。
8086有20位地址總線,與CPU內部結構的16位不同。
采用一種在內部使用兩個16位地址合成的方法來形成一個20位的物理地址。
物理地址=段地址*16 + 偏移地址
尋址模式的本質含義是:CPU在訪問內存時,用一個基礎地址和一個相對于基礎地址的偏移地址相加,給出內存單元的物理地址。
所以,也可由此看出系統的CPU結構、地址總線、數據總線和控制總線寬度是不一定相同的。
提問:386之后的機器呢?
回答:
8080處理器擁有16位地址總線和8位數據總線;
8086內、外部數據總線均為16位,地址總線為20位;
80286內部和外部數據總線皆為16位,地址總線為24位;
80386,80486的內部和外部數據總線都是32位,地址總線也是32位;
Pentium是64位數據總線,32位地址總線;
Pentium Pro是64位數據總線,地址總線就已經上升為36根了。
具體可見下圖,來自于《80x86匯編語言程序設計》:

段的概念:內存并沒有分段,段的劃分來自于CPU。在編程時根據需要,將若干地址連續的內存單元看做一個段,用段地址*16定位段的起始地址(基礎地址),用偏移地址定位段中的內存單元。
在8086CPU加電啟動或復位后,CS和IP被設置為CS=FFFFH,IP=0000H,即在8086PC機剛啟動時,CPU從內存FFFF0H單元中讀取指令執行,FFFF0單元中的指令是8086PC機開機后執行的第一條指令。
第3章實驗2最后一題的猜測:
在網上看到別人的答案都是說,由于把此處的位置當做棧了,而t產生中斷,所以就將 標識寄存器、CS、IP入棧保存。不過我發現除了以上之外,還總是保存了另外兩個寄存器的內容,其順序分別是:
ax,bp,ip,cs,eflags
----不知道為什么總是還保存了bp和ax。
DOS方式下,一般情況下,0:200~0:2ff空間中沒有系統或其他程序的數據和代碼;這是一段安全的空間!其實這屬于中斷向量表的空間,只是一般這一段的中斷向量表項都是空的。
DOS加載exe:
1、程序加載后,ds中存放著程序所在內存區的段地址,這個內存區的偏移地址為0,則程序所在的內存區的地址為ds:0.
2、這個內存區的前256個字節中存放的是PSP,DOS用來和程序進行通信。從256(100H)字節處向后的空間存放的是程序。
3、CX寄存器存放的程序的長度。
即是:從ds中可以得到PSP的段地址SA,PSP的偏移地址為0,則物理地址為SA*16+0.
程序的物理地址為SA*16+0+256=SA*16+16*16+0=(SA+16)*16+0=SA+10H:0
第7章 更靈活的定位內存地址的方法
“如果一個問題的解決方案,使我們陷入一種矛盾之中。那么,很可能是我們考慮問題的出發點有了問題,或是說,我們起初運用的規律并不合適。”這段話包含很深刻的道理,不僅僅適用于計算機問題,技術問題,同樣適用于生活中,人生上所有的問題。
更靈活的方式來指明內存單元:[bx+idata].寫法:
mov ax,[bx+200]
mov ax,[200+bx]
mov ax,200[bx]
mov ax,[bx].200
si、di是兩個和bx功能類似的寄存器,但是這兩個不能拆分成兩個8位寄存器。
[bx+si] ~ [bx+di] ~ [bx][si] ~ [bx][di]
[bx+si+idata] ~ [bx+di+idata]
mov ax,[bx+si+200]
mov ax,[bx+200+si]
mov ax,[200+bx+si]
mov ax,200[bx][si]
mov ax,[bx].200[si]
mov ax,[bx][si].200
本章結束語:
“下一章中,我們將對尋址方式的問題進行更深入地探討。之所以如此重視這個問題,是因為尋址方式的適當應用,使我們可以以更合理的結構來看待所要處理的數據。而為所要處理的看似雜亂的數據設計一種清晰的數據結構是程序設計的一個關鍵問題。”
第8章 數據處理的兩個基本問題
計算機是進行數據處理、運算的機器,那么有兩個基本的問題就包含在其中:
1、處理的數據在什么地方?
2、要處理的數據有多長?
匯編語言中用3個概念來表達數據的位置:
1、立即數:執行前在CPU的指令緩沖器中,在匯編指令中直接給出。
2、寄存器:指令要處理的數據在寄存器中,在匯編指令中給出相應的寄存器名。
3、段地址(SA)和偏移地址(EA):指令要處理的數據在內存中,在匯編指令中可用[x]的格式給出EA,SA在某個段寄存器中。
當數據存放在內存中的時候,我們可以用多種方式來給定這個內存單元的偏移地址,這種定位內存單元的方法一般被稱為尋址方式。尋址方式參見8.4節的尋址方式表。
匯編語言用以下方法處理數據長度的問題:
1、通過寄存器名指明要處理的數據的尺寸。
2、在沒有寄存器名存在的情況下,用操作符X ptr指明內存單元的長度,X在匯編指令中可以為word或byte。
3、其他方法:有些指令默認了訪問的是字單元還是字節單元,比如,push、pop指令只進行字操作。
div指令:除法指令,使用div做除法的時候應注意以下問題:
1、除數:有8位和16位兩種,在一個reg或內存單元中。
2、被除數:默認放在AX或DX和AX中,如果除數為8位,被除數則為16位,默認在AX中存放;如果除數為16位,被除數則為32位,在DX和AX中存放,DX存放高16位,AX存放低16位。
3、結果:如果除數為8位,則AL存儲除法操作的商,AH存儲除法操作的余數;如果除數為16位,則AX存儲除法操作的商,DX存儲除法操作的余數。
第9章 轉移指令的原理
可以修改IP,或同時修改CS和IP的指令統稱為轉移指令。
8086CPU的轉移指令分為以下幾類:
1、無條件轉移指令(如jmp)。
2、條件轉移指令
3、循環指令(如loop)。
4、過程
5、中斷
offset操作符在匯編語言中是由編譯器處理的符號,它的功能是取得標號的偏移地址。
段內短轉移
jmp short 標號 功能:IP=IP+8位位移
1、8位位移=標號處的地址-jmp指令后的第一個字節的地址;
2、short指明此處的位移為8位位移;
3、8位位移的范圍為-128~127,用補碼表示;
4、8位位移由編譯程序在編譯時算出。
段內近轉移
jmp near ptr 標號 功能:IP=IP+16位位移
1、16位位移=標號處的地址-jmp指令后的第一個字節的地址;
2、near ptr指明此處的位移為16位位移,進行的是段內近轉移;
3、16位位移的范圍為-32768~32767,用補碼表示;
4、16位位移由編譯程序在編譯時算出。
段間轉移
jmp far ptr 標號 實現的是段間轉移,又稱為遠轉移。功能:
cs=標號所在段的段地址;ip=標號在段中的偏移地址。
far ptr指明了指令用標號的段地址和偏移地址修改CS和IP。
所有的有條件轉移指令都是短轉移,在對應的機器碼中包含轉移的位移,而不是目的地址。對IP的修改范圍都為-128~127.
jcxz 標號 == if((cx)==0) jmp short 標號
所有的循環指令都是短轉移,在對應的機器碼中包含轉移的位移,而不是目的地址。對IP的修改范圍都為-128~127.
loop 標號 == (cx)--;if((cx)!=0) jmp short 標號
段內轉移對IP的修改時根據轉移目的地址和轉移起始地址之間的位移來進行的。在它們對應的機器碼中不包含轉移的目的地址,而包含的是到目的地址的位移。這種設計,方便了程序段在內存中的浮動裝配。
注意,根據位移進行轉移的指令,它們的轉移范圍受到轉移位移的限制,如果在源程序中出現了轉移范圍超界的問題,在編譯的時候,編譯器將報錯。---看到這個結論,我心里高興放心多了,不然我還擔心要我自己去算轉移位移呢!
第10章 call和ret指令
call和ret指令都是轉移指令,他們都修改ip,或同時修改cs和ip。他們經常被共同用來實現子程序的設計。
ret指令用棧中的數據,修改ip的內容,從而實現近轉移。
retf指令用棧中的數據,修改cs和ip的內容,從而實現遠轉移。
ret == "pop IP"
retf == "pop IP ; pop CS"
CPU執行call指令時,進行兩步操作:
1、將當前的IP或CS和IP壓入棧中;
2、轉移。
call 標號 == “push IP ; jmp near ptr 標號”
call far ptr 標號 == “push CS ; push IP ; jmp far ptr 標號”
call 16位reg == "push IP ; jmp 16位reg"
call word ptr 內存單元地址 == "push IP ; jmp word ptr 內存單元地址"
call dword ptr 內存單元地址 == "push CS ; push IP ;jmp dword ptr 內存單元地址"
mul乘法指令:
1、兩個相乘的數,要么都是8位,要么都是16位。如果是8位,一個默認在AL中,另一個放在8位reg或內存單元中;如果是16位,一個默認在AX中,另一個放在16位reg或內存字單元中。
2、結果:如果是8位乘法,結果默認放在AX中;如果是16位乘法,結果高位默認在DX中,低位在AX中放。
第11章 標志寄存器
標志寄存器的3種作用:
1、用來存儲相關指令的某些執行結果;
2、用來為CPU執行相關指令提供行為依據;
3、用來控制CPU的相關工作方式。
flag和其他寄存器不一樣,其他寄存器是用來存放數據的,都是整個寄存器具有一個含義。而flag寄存器是按位起作用的,也就是說,它的每一位都有專門的含義,記錄特定的信息。
flag寄存器各位示意圖:

flag的1、3、4、12、13、14、15位在8086CPU中沒有使用,不具有任何含義。
CF:進位標志位。一般情況下,在進行無符號數運算的時候,它記錄了運算結果的最高有效位向更高位的進位值,或從更高位的借位值。
PF:奇偶標志位
AF:
ZF:零標志位
SF:符號標志位
DF:方向標志位
OF:溢出標志位。一般情況下,OF記錄了有符號數運算的結果是否發生了溢出。如果發生溢出,OF=1;如果沒有,OF=0.
一定要注意CF和OF的區別:CF是對無符號數運算有意義的標志位,而OF是對有符號運算有意義的標志位。
adc帶進位加法指令,它利用了CF位上記錄的進位值。
格式:adc op1,op2
功能: op1=op1+op2+CF
注意:如果用到這個指令,一定要密切注意所有可能影響CF標志的指令?。?!
sbb帶借位減法指令,它利用了CF位上記錄的借位值。
格式:sbb op1,op2
功能:op1=op1-op2-CF
注意:如果用到這個指令,一定要密切注意所有可能影響CF標志的指令?。?!
CPU提供了cmp指令,也提供了je等條件轉移指令,如果將它們配合使用,可以實現根據比較結果進行轉移的功能。但這只是“如果”,只是一種合理的建議,和事實上常用的方法。但究竟是否配合使用它們,完全是你自己的事情。這就好像call和ret指令的關系一樣。
DF標志和串傳送指令
DF:方向標志位。在串處理指令中,控制每次操作后si、di的增減。
df=0 每次操作后si、di遞增;
df=1 每次操作后si、di遞減。
cld指令:將標識寄存器的df位置0
std指令:將標識寄存器的df位置1
串傳送指令:
movsb:將ds:di指向的內存單元中的字節送入es:di中,然后根據標志寄存器df位的值,將si和di遞增或遞減。
功能相當于如下幾步:
1、((es)*16+(di))=((ds)*16+(si))
2、如果df=0,則:(si)=(si)+1 , (di)=(di)+1
如果df=1,則:(si)=(si)-1 , (di)=(di)-1
movsw:將ds:di指向的內存單元中的字送入es:di中,然后根據標志寄存器df位的值,將si和di遞增2或遞減2。
功能相當于如下幾步:
1、((es)*16+(di))=((ds)*16+(si))
2、如果df=0,則:(si)=(si)+2 , (di)=(di)+2
如果df=1,則:(si)=(si)-2 , (di)=(di)-2
movsb和movsw進行的是串傳送操作中的一個步驟,一般來說,movsb和movsw都和rep配合使用,格式如下:
rep movsb.用匯編語法來描述rep movsb的功能就是:
s:movsb
loop s
pushf的功能是將標志寄存器的值壓棧,而popf是從棧中彈出數據,送入標志寄存器中。
pushf和popf,為直接訪問標志寄存器提供了一種方法。
第12章 內中斷
中斷向量表:對于8086PC機,中斷向量表指定放在內存地址0處。從內存0000:0000到0000:03FF的1024個單元中存放。
中斷向量表的一個表項占兩個字,高地址字存放段地址,低地址字存放偏移地址。
8086CPU在收到中斷信息后,引發中斷過程:
1、從中斷信息中取得中斷類型碼;
2、標志寄存器的值入棧;
3、設置標志寄存器的第8位TF和第9位IF的值為0;
4、CS的內容入棧;
5、IP的內容入棧;
6、從內存地址為中斷類型碼*4 和 中斷類型碼*4+2 的兩個字單元中讀取中斷處理程序的入口地址設置IP和CS。
更簡潔的描述:
1、取得中斷類型碼N;
2、pushf
3、TF=0,IF=0
4、push CS
5、push IP
6、(IP)=(N*4),(CS)=(N*4+2)
TF和IF設為0,是為了避免在中斷程序處理過程中還是單步調試狀態。
中斷處理程序的編寫方法和子程序的比較相似,下面是常規步驟:
1、保存用到的寄存器;
2、處理中斷;
3、恢復用到的寄存器;
4、用iret指令返回。
iret指令的功能用匯編語法描述為:
pop IP
pop CS
popf
定制中斷處理程序,就是將中斷處理程序代碼寫到固定的內存地址,然后修改中斷向量表中該中斷類型對應的處理程序的偏移地址。
第13章 int指令
int指令和iret指令的配合使用與call指令和ret指令的配合使用具有相似的思路。
編寫中斷例程,就類似于編寫子程序,我們希望中斷處理完成后能繼續回到原程序繼續運行,所以應該使得中斷例程返回。像上一章中中斷程序用int 21h終止進程的情況是很特殊的。不過要注意的是,中斷例程的返回需要用iret!
BIOS和DOS所提供的中斷例程
在系統板的ROM中存放著一套程序,稱為BIOS(基本輸入輸出系統),BIOS中主要包含以下幾部分內容。
1、硬件系統的檢測和初始化程序;
2、外部中斷和內部中斷的中斷例程;
3、用于對硬件設備進行I/O操作的中斷例程;
4、其他和硬件系統相關的中斷例程。
操作系統DOS也提供了中斷例程,從操作系統的角度來看,DOS的中斷例程就是操作系統向程序員提供的編程資源。
BIOS和DOS在所提供的中斷例程中包含了許多子程序,這些子程序實現了程序員在編程的時候經常需要用到的功能。程序員在編程的時候,可以用int指令直接調用BIOS和DOS提供的中斷例程,來完成某些工作。
和硬件設備相關的DOS中斷例程中,一般都調用了BIOS的中斷例程。
BIOS和DOS中斷例程安裝過程:
1、開機后,CPU一加電,初始化CS=0FFFFH,IP=0,自動從FFFF:0單元開始執行程序。FFFF:0處有一條跳轉指令,CPU執行該指令后,轉去執行BIOS中的硬件系統檢測和初始化程序。
跳轉指令:jmp F000:998A
此處的指令不可修改!
2、初始化程序將建立BIOS所支持的中斷向量,即將BIOS提供的中斷例程的入口地址登記在中斷向量表中。注意,對于BIOS所提供的中斷例程,只需將入口地址登記在中斷向量表中即可,因為它們是固化到ROM中的程序,一直在內存中存在。
3、硬件系統檢測和初始化完成后,調用int 19h進行操作系統的引導。從此將計算機交由操作系統控制。
證明int 19h只是BIOS提供的功能。
4、DOS啟動后,除完成其他工作外,還將它所提供的中斷例程裝入內存,并建立相應的中斷向量。
BIOS中斷例程:
int 10h中斷例程是BIOS提供的中斷例程,其中包含了多個和屏幕輸出相關的子程序。
一般來說,一個供程序員調用的中斷例程中往往包括多個子程序,中斷例程內部用傳遞進來的參數來決定執行哪一個子程序。BIOS和DOS提供的中斷例程,都用ah來傳遞內部子程序的編號。
DOS中斷例程:
int 21h中斷例程是DOS提供的中斷例程,其中包含了DOS提供給程序員在編程時調用的子程序。
第14章 端口
我們前面講過,各種存儲器都和CPU的地址線、數據線、控制線相連。CPU在操控它們的時候,把它們都當做內存來對待,把它們總地看做一個由若干存儲單元組成的邏輯存儲器,這個邏輯存儲器我們稱其位內存地址空間。
在PC機系統中,和CPU通過總線相連的芯片除各種存儲器外,還有以下3中芯片。
1、各種接口卡(比如,網卡、顯卡)上的接口芯片,他們控制接口卡進行工作;
2、主板上的接口芯片,CPU通過它們對部分外設進行訪問;
3、其他芯片,用來存儲相關的系統信息,或進行相關的輸入輸出處理。
在這些芯片中,都有一組可以由CPU讀寫的寄存器。這些寄存器,它們在物理上可能處于不同的芯片中,但是他們在以下兩點上相同。
1、都和CPU的總線相連,當然這種連接是通過它們所在的芯片進行的。
2、CPU對它們進行讀或寫的時候都通過控制線向它們所在的芯片發出端口讀寫命令。
可見,從CPU的角度,將這些寄存器都當做端口,對它們進行統一編址,從而建立了一個統一的端口地址空間。每一個端口在地址空間中都有一個地址。
#######問題:
1、如何將某個芯片綁定到某個端口?還是操作系統預設的?那要是出現沖突怎么辦?
2、端口地址空間被內存地址空間是同一個嗎?也就是說:端口地址空間是內存地址空間的一個子集,還是另一個獨立的地址空間?
3、這里講的端口與網絡程序中說的端口是一個概念嗎?
CPU可以直接讀寫以下3個地方的數據。
1、CPU內部的寄存器;
2、內存單元;
3、端口。
端口的讀寫
在訪問端口的時候,CPU通過端口地址來定位端口,因為端口所在的芯片和CPU通過總線相連,所以,端口地址和內存地址一樣,通過地址總線來傳送。在PC系統中,CPU最多可以定位64KB個不同的端口。則端口地址的范圍為0~65535.
對端口的讀寫不能用mov、push、pop等內存讀寫指令。端口的讀寫指令只有兩種:in和out,分別用于從端口讀取數據和往端口寫入數據。
注意,在in和out指令中,只能使用ax或al來存放從端口中讀入的數據或要發送到端口中的數據。訪問8為端口時用al,訪問16位端口時用ax。
對0~255以內的端口進行讀寫時,地址直接寫端口號。
in al,20h ;從20h端口讀入一個字節
out 20h,al ;往20h端口寫入一個字節
對256~65535的端口讀寫時,端口號放在dx中。
mov dx,3f8h ;將端口號3f8h送入dx
in al,dx ;從3f8h端口讀入一個字節
out dx,al ;想3f8h端口寫入一個字節
對存儲芯片的操作需要兩個端口:地址端口和數據端口,讀寫分兩步進行,先將單元號送地址端口,然后再利用數據渡口進行讀或者寫。
但對一些別的外設,比如鍵盤輸入,就只有一個端口。
但是如何知道一個芯片到底有多少個有效單元呢?有指令能查詢嗎?
shl和shr邏輯移位指令:
shl是邏輯左移指令,功能為:
1、將一個寄存器或內存單元中的數據向左移位;
2、將最后移出的一位寫入CF中;
3、最低位用0補充。
如果移動位數大于1時,必須將移動位數放在cl中。
shr是邏輯右移指令,功能為:
1、將一個寄存器或內存單元中的數據向右移位;
2、將最后移出的一位寫入CF中;
3、最高位用0補充。
如果移動位數大于1時,必須將移動位數放在cl中。
第15章 外中斷
在PC系統中,外中斷源一共有以下兩類:
1、可屏蔽中斷
可屏蔽中斷是CPU可以不響應的外中斷。CPU是否相應可屏蔽中斷,要看標志寄存器的IF位的設置。當CPU檢測到可屏蔽中斷信息時,如果IF=1,則CPU在執行完當前指令后相應中斷,引發中斷過程;如果IF=0,則不響應可屏蔽中斷。
2、不可屏蔽中斷
不可屏蔽中斷是CPU必須響應的外中斷。當CPU檢測到不可屏蔽中斷信息時,則在執行完當前指令后,立即響應,引發中斷過程。
對于8086CPU,不可屏蔽中斷的中斷類型碼固定為2,所以中斷過程中,不需要取中斷類型碼。
幾乎所有由外設引發的外中斷,都是可屏蔽中斷。
CPU對外設輸入的通常處理方法:
1、外設的輸入送入端口;
2、向CPU發出外中斷(可屏蔽中斷)信息;
3、CPU檢測到可屏蔽中斷信息,如果IF=1,CPU在執行完當前指令后響應中斷,執行響應的中斷例程;
4、可在中斷例程中實現對外設輸入的處理。
端口和中斷機制,是CPU進行I/O的基礎。
第16章 直接定址表
注意:標號定位的是絕對地址,如果需要將程序安裝到別的地址,類似于中斷程序,由標號定位的地址可能產生錯誤。
《80x86匯編語言程序設計教程》學習筆記
8086指令系統
8086指令系統可分為如下六個功能組:
1、數據傳送
2、算術運算
3、邏輯運算
4、串操作
5、程序控制
6、處理器控制
對于每一條指令,程序員要注意:
1、指令的功能;
2、適用于指令的操作數的尋址方式;
3、指令對標志的影響;
4、指令的長度和執行時間。
數據傳送指令組又可分為:傳送指令,交換指令,地址傳送指令,堆棧操作指令,標志傳送指令,查表指令,輸入輸出指令。
除了SAHF和POPF指令外,這組指令對各標志沒有影響。
傳送指令mov;變換指令xchg;
地址傳送指令LEA:lea reg,oprd 該指令把操作數oprd的有效地址傳送到操作數reg。
LDS:lds reg,oprd 該指令把操作數oprd中所含的一個32位地址指針的段值部分送到數據段寄存器DS,把偏移部分送到指令給出的通用寄存器REG。
LES:les reg,oprd 該指令把操作數oprd中所含的32位地址指針的段值部分送到附加段寄存器ES,把偏移部分送到指令給出的通用寄存器reg。
入棧push;出棧pop。
標志傳送指令:
LAHF:該指令把標志寄存器的低8位(包括SF、ZF、AF、PF、CF)傳送到AH的指定位。
SAHF:與LAHF相反,把AH的指定位送到標志寄存器的低8位。
PUSHF/POPF.
標志位操作指令,屬于處理器控制指令組:
CLC:使進位標志為0
STC:使進位標志為1
CMC:使進位標志取反。
CLD:使方向標志DF=0.
STD:使DF=1
CLI:IF=0
STI:IF=1