?? 匯011.txt
字號:
例11.3 檢測是否有“0作除數”的錯誤。
FDIV DATA1 ;用協處理器中堆頂數據去除DATA1
FSTSW AX ;把狀態寄存器的值傳送給AX
TEST AX, 4 ;測試第2位,即:檢測ZE是否為1
JNZ DIV_ERR
例11.4 檢測是否有“非法操作數”的錯誤。
FSQRT ;求協處理器中堆頂數據的平方根
FSTSW AX
TEST AX, 1 ;測試第0位,即:檢測IE是否為1
JNZ SQRT_ERR
方法2:用SAHF指令把AX的低字節傳送給CPU的標志位寄存器,然后再用條件轉移指令來完成相應的檢測。
例11.5 檢測內存單元的數據與協處理器堆頂數據之間的大小關系。
FCOM DATA1 ;內存單元DATA1的值與協處理器堆頂數據進行比較
FSTSW AX
SAHF ;把AX的低字節存入CPU的狀態寄存器
JE ST_EQUAL ;具體大小關系的決定可見表11.2中的“FCOM”
JB ST_BELOW
JA ST_ABOVE
11.2.3 控制寄存器
控制寄存器主要用于浮點數精度選擇的控制、四舍五入的控制和無窮大的控制等,其低6位還可用來決定是否屏蔽協處理器的異常。指令FLDCW可用來設置控制寄存器的值??刂萍拇嫫髦锌刂莆坏姆植既鐖D11.6所示,其控制位的含義如表11.3所列。
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
IC
RC
PC PM UM OM ZM DM IM
圖11.6 控制寄存器的控制位分布示意圖
表11.3 控制寄存器中控制位的含義
控制位 控制功能說明
IC(無窮大控制) 0—投影,假定是無符號無窮;
1—仿射,允許正、負無窮
RC(舍入控制) 00—最接近或偶數,01—舍入成負無窮,
11—舍入成負無窮,10—截成0
PC(精度控制) 00—單精度,01—保留,11—雙精度,10—擴展精度
PM 精度錯誤屏蔽位
若屏蔽位的值為1,則狀態寄存器的相應位被屏蔽。
UM 下溢出屏蔽位
OM 上溢出屏蔽位
ZM 除數為0屏蔽位
DM 非規格化操作數屏蔽位
IM 非法操作屏蔽位
11.2.4 標記寄存器
標記寄存器用來表明協處理器堆棧中各存儲單元內容的狀態,也就是說,該寄存器可表明堆棧中的數據是合法的,還是非法的,是無窮,還是0或空等。該標記寄存器的結構如圖11.7所示。
15 13 11 9 7 5 3 1 0
TAG(7) TAG(6) TAG(5) TAG(4) TAG(3) TAG(2) TAG(1) TAG(0)
圖11.7 標記寄存器結構示意圖
其中:TAG(i)的取值含義:00—合法,01—0,10—非法或無窮,11—空
在協處理器中,查看標記寄存器的方法是使用指令FSTENV、FSAVE或FRSTOR,它們都能使標記寄存器與其它協處理器數據一起轉存。
11.3 協處理器的指令系統
協處理器共有68條不同的指令,匯編程序在遇到協處理器指令助憶時,都會將其轉換成機器語言的ESC指令,ESC指令代表了協處理器的操作碼。
在協處理器指令在執行過程中,需要訪問內存單元時,CPU會為其形成內存地址。協處理器在協處理器指令期間內利用數據總線來傳遞數據。80287協處理器利用I/O地址00FAH~00FFH來實現其與CPU之間的數據交換,而80387~Pentium系列芯片,則是利用I/O地址800000FAH~800000FFH來實現這兩者之間的數據交換。
11.3.1 指令操作符的命名規則
協處理器指令的操作符(或助憶符)在命名設計時,遵循了下列規則:
1、在操作符后面加上字母P:表示該指令執行完后,還進行一次堆棧彈出操作。如:FADD和FADDP等;
2、在操作符后面加上字母R:表示該操作是反模式,它僅限于減法、除法指令。如:FSUB和FSUBR等;
正模式 —— 棧頂數據=棧頂數據 op 指令操作數,或OPN1=OPN1 – OPN2
反模式 —— 棧頂數據=指令操作數 op 棧頂數據,或OPN1=OPN2 – OPN1
假設:棧頂數據為10,內存變量data的值為1,分別執行下列指令將有不同的結果。
FSUB data ;指令執行后,棧頂數據為9
FSUBR data ;指令執行后,棧頂數據為-9
FSUB ST, ST(1) ;指令執行后,ST=ST-ST(1)
FSUBR ST, ST(1) ;指令執行后,ST=ST(1)-ST
3、操作符的第2個字母是I:表示內存中數據是整數。它對加、減、乘除指令都有效。
例如:FADD data——浮點數加法;
FIADD data——整數加法,它表示內存單元data是一個整數,把該整數加到棧頂的浮點數上。
4、操作符的第2個字母是N:表示在指令執行之前檢查非屏蔽數值性錯誤。如:FSAVE和FNSAVE等,前者稱為等待形式(wait version),后者稱為非等待形式(no-wait version)。
在使用.8087偽指令情況下,匯編程序會在等待形式的指令前面加上指令WAIT,而在非等待形式的指令前面加上空操作指令NOP。
理解了上述操作符命名規則,就能很容易地區分同類指令之間的差異。
11.3.2 數據傳送指令
為了滿足協處理器和CPU之間進行數據交流的需求,就需要實現內存單元和協處理器之間進行數據傳送的指令。協處理器的指令系統中有三大類數據傳送指令:BCD傳送指令、浮點數傳送和整數傳送指令。
一、BCD傳送指令
1、FBLD
指令格式:FBLD MemBCD(*)
指令功能:將內存中的BCD數據壓入協處理器的堆棧中;
(*) MemType是指定數據類型Type的內存單元,如:MemBCD是BCD類型的存儲單元。此后不再說明。
2、FBSTP
指令格式:FBSTP MemBCD
指令功能:將協處理器中的BCD數據存入內存,并進行堆棧的彈出操作。
例如:
.387
data1 DT 123, -543
data2 DT 2.5
……
FBLD data1 ;把BCD數據123壓進棧
FBSTP data2 ;把當前堆頂數據彈出,并傳送給BCD型的內參單元
二、浮點數傳送指令
1、FLD
指令格式: FLD STReg(*)/MemReal
指令功能: 將浮點數據壓入協處理器的堆棧中。當進行內存單元內容壓棧時,系統會自動決定傳送數據的精度。比如:用DD或REAL4定義的內存單元數值是單精度數等。
(*) STReg是協處理器堆棧寄存器ST(0)~ST(7)。
例如:
.387
data1 DD 123, -543
data2 REAL8 -321.5
data3 REAL10 2.5
……
FLD data1 ;壓一個單精度數據進棧
FLD data2 ;壓一個雙精度數據進棧
FLD ST(0) ;把堆棧寄存器ST(0)的值再壓進棧
FLD data3 ;壓一個擴展精度數據進棧
2、FST 指令格式: FST STReg/MemReal
指令功能: 將協處理器堆棧棧頂的數據傳送到目標操作數中。在進行數據傳送時,系統自動根據控制寄存器中舍入控制位的設置把棧頂浮點數舍入成相應精度的數據。
3、FSTP
指令格式: FSTP STReg/MemReal
指令功能: 與FST相類似,所不同的是:指令FST執行完后,不進行堆棧的彈出操作,即:堆棧不發生變化,而指令FSTP執行完后,則需要進行堆棧的彈出操作,堆棧將發生變化。請見11.3.1節中的指令操作符命名規則的說明。
4、FXCH
指令格式: FXCH [STReg]
指令功能: 將指定的寄存器中的浮點數與堆頂浮點數進行交換。如果不指定操作數,那么,默認ST和ST(1)二者之間交換數據。
例如:FXCH ST(2)——棧頂數據與堆棧寄存器ST(2)進行數據交換。
三、整數傳送指令
1、FILD
指令格式:FILD MemInt
其中:MemInt是定義為整型數據類型的內存單元,但不能是用DB定義的存儲單元。下同,不再敘述。
2、FIST/FISTP
指令格式: FIST MemInt
FISTP MemInt
其中: Mem是定義整型數據類型的內存單元,但不能是用DB定義的存儲單元。
指令功能: 將協處理器堆棧棧頂的數據傳送到目標存儲單元中。在進行數據傳送時,系統自動根據控制寄存器中舍入控制位的設置把棧頂浮點數舍入成整型數據。
指令FIST和FISTP的區別在于堆棧操作,詳細請見11.3.1中的命名規則說明。
11.3.3 數學運算指令
在協處理器的指令系統中,有關數學運算指令有:加法指令、減法指令、乘法指令、除法指令和求平方根指令等。涉及數學運算的指令有比例運算、舍入運算、求絕對值運算和改變數值符號運算等指令。
1、加法指令
指令格式: FADD [STReg1, STReg2](*)
FADD MemReal
FADDP STReg, ST
FIADD MemInt
(*) 在此指令格式下,如果同時指定了二個堆棧寄存器,那么,其中一個寄存器必須是ST。其它指令的同類格式與此同理。
指令FADD含有二個隱含操作數ST(1)和ST,其運算功能是:從堆棧中彈出這二個操作數,然后把計算的“和”壓入堆棧,即:ST=ST(1)+ST。
指令“FADD MemReal”的功能:ST=ST+MemReal
指令“FADDP STReg, ST”的功能:STReg=STReg+ST,并彈出堆棧的棧頂
指令“FIADD MemInt”的功能:ST=ST+MemInt
2、減法指令
指令格式: FSUB [STReg1, STReg2]
FSUB MemReal
FSUBP STReg, ST
FISUB MemInt
FSUBR [STReg1, STReg2] ;后四條指令是前四條指令的反模式形式
FSUBR MemReal
FSUBRP STReg,ST
FISUBR MemInt
指令FSUB含有二個隱含操作數ST(1)和ST,其運算功能是:從堆棧中彈出這二個操作數,然后把計算的“差”壓入堆棧,即:ST=ST(1)-ST。
指令“FSUB MemReal”的功能:ST=ST-MemReal
指令“FSUBP STReg, ST”的功能:STReg=STReg-ST,并彈出堆棧的棧頂
指令“FISUB MemInt”的功能:ST=ST-MemInt
反模式的四條指令的功能在此從略,請參閱11.3.1中的有關說明。
3、乘法指令
指令格式: FMUL [STReg1, STReg2]
FMUL MemReal
FMULP STReg, ST
FIMUL MemInt
4、除法指令
指令格式: FDIV [STReg1, STReg2]
FDIV MemReal
FDIVP STReg, ST
FIDIV MemInt
FDIVR [STReg1, STReg2] ;后四條指令是前四條指令的反模式形式
FDIVR MemReal
FDIVRP STReg, ST
FIDIVR MemInt
例如:
.387
word1 DW 20
data1 REAL8 8
data2 REAL8 -2
data3 REAL8 -12
……
FLD data1 ;本例只是顯示指令的使用方法,無具體的實際功能
FLD data2
FLD data3
FDIV ST(2), ST
FDIV data1
FDIVP ST(2), ST
FIDIV word1
5、其它數學運算指令
在協處理器中,除了完成具體的數學運算指令外,還設置了若干個與數學運算有關的運算指令。具體的運算指令及其功能描述如表11.4所列。
表11.4 與數學運算有關的其它指令
指令格式
指令的功能
FSQRT
求棧頂數據的平方根。如果對負數求其平方根,則會發生錯誤,并可通過檢測狀態寄存器的標志位IE來確定。
FSCALE
將ST(1)中的數(轉換成整數)加上ST的階碼,該指令能快速完成乘/除2n的運算。ST(1)中的數必須在2-15到215之間。
FPREM/FPREM1
ST=ST%ST(1),80387及其以后的協處理器支持FPREM1。
FRNDINT
對棧頂數據進行舍入運算,使之轉換成整數。
FXTRACT
將棧頂數據分成二部分:無偏階碼和尾數。尾數存入棧頂,無偏階碼存入ST(1)。它常用將浮點數轉換成小數形式打印輸出。
FABS
ST=|ST|,即:求棧頂數據的絕對值。
FCHS
ST=-ST,即:改變棧頂數據的符號。
11.3.4 比較運算指令
使用比較指令是將棧頂中的數與其它操作數進行比較,比較結果存于狀態寄存器的條件編碼位C3~C0處(參閱表11.2)。具體的比較運算指令及其功能描述如表11.5所列。
表11.5 比較運算指令及其功能
指令格式
指令的功能
FCOM
將棧頂數據與另一個操作數進行比較,該操作數可以存儲在堆棧寄存器中,也可存儲在內存中。
當在指令中不指定操作數時,其默認的操作數是ST和ST(1)。
FCOMP/FCOMPP
此指令的比較功能與FCOM相一致,所不同的是指出從堆棧中彈出一個,還是二個數據。
FICOM MemInt
FICOMP MemInt
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -