第十八課浮點反匯編分析_第1頁
第十八課浮點反匯編分析_第2頁
第十八課浮點反匯編分析_第3頁
第十八課浮點反匯編分析_第4頁
第十八課浮點反匯編分析_第5頁
免費預覽已結束,剩余20頁可下載查看

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、浮點寄存器棧的棧頂指針在狀態(tài)寄存器的(OZ (OZ 。共 位合計 個數值,分別為 ,也就是 ,指示當前的棧頂位置在哪個浮點寄存器上。假如為 ,則浮點寄存器棧頂位于 ,68 。執(zhí)行一條 ,2*,相當于 執(zhí)行一條 6;9. 指令,狀態(tài)寄存器的 (OZ (OZ 減 ,變成了 ,這時 :56 指針指向 ,68 。 再把值寫入 9: 條件碼() ) ): 的條件碼作用相當于 中的+LRGMY 寄存器的條件碼的作用。棧頂指針(:56):棧頂指針 是 浮點寄存器的索引值。共 個值,分別指示 ,68 ,68 ,在匯編語法層,9:( )表示棧頂浮點仿真庫的實現與 ) 浮點庫反匯編分析之六 ,6; 編程 ,6;

2、編程前面幾章都是講述計算原理,在 )6; 支持的基本整型的基礎建立了幾個類型模板,支持通用用的 (也即沒有長度或精度限制的)整型計算、定點數計算、浮點數計算、基本函數計算,實際上是實現了個 ) 仿真庫。這些內容雖然對理解計算原理非常重要,但 除了)-;可能在領域有點價值之外,其他的幾個模板應用價值均不大。目前,支持 /+ 標準的浮點硬件已經普及。通用 )6; 均已內置了浮點單元,最大可支持擴展雙精度類型,足以滿足一般計算的需要。特殊環(huán)境 下的開發(fā)(例如系統(tǒng))即使沒有浮點硬件,編譯器也可能提供基本的仿真庫。畢竟,浮點運算已經是 ) ) 不可或缺的一部分。而且,在編譯器中實現一 兩種浮點類型(例如

3、單精度類型和雙精度類型),技術難度和工作量并不大(本書的代碼就是一個證明),,58:84 早在幾十年前就是這么做的。因此,在實 際的開發(fā)工作中,重要的不是自己實現已經實現的東西,而且如何更好地控制浮點硬件,從而得到更穩(wěn)定、更高效的代碼。自然,正如 )6; 一樣,每一個浮點硬件系統(tǒng)都是不一樣的,且不提運算過程的處理細節(jié),即使是編程 模型、指令集也會有很大的區(qū)別,因此講述所有的浮點硬件是不現實的。不過,它們一般都遵循 /+ 標準,這意味著在邏輯層面,它們是大同小異的,因此講述 所有的浮點硬件也是沒有必要的。+2 的 系列的 )6; 是目前 6) 的主流,它內置的浮點處理單元 ,6;(早年是 數學協(xié)

4、處理器)因而也成了最常用的浮點硬件。本章就以 ,6; 為例講述浮點硬件編程,而后面的幾章將反匯編分析建立在 ,6; 之上的 ) 浮點庫,從而得到計算編程系統(tǒng)的完整印象。 ,6; 簡史早在 位的 年代, 就作為 的數學協(xié)處理器出現。當時的 是一個與 分離的的浮點指令,但浮點指令與其他 指令混,它使用的浮點指令是合在一起執(zhí)行。后來,在 中, ,6; 出現了,取代了原先的協(xié)處理器,這是 ,6;在 / 體系中的首次出現。 ,6; 延續(xù)了協(xié)處理器的浮點指令集。 編程環(huán)境 ,6; 有的指令和配套的寄存器。它的指令是 浮點指令,配套的寄存器有: 個 位的數據寄存器、 個 位的控制寄存器、 個 位的狀態(tài)寄存

5、器、 個 位的標志寄存器、 個最后指令地址寄存器、 個最后操作數寄存器、 個操作碼寄存器。其中,最后 個寄存器用于最后一次操作的信息,主要 用于異常處理。編程主要是圍繞數據寄存器堆棧、狀態(tài)寄存器和控制寄存器進 行的,其他部分則多用于調試支持。 數據寄存器(*GZG 8KMOYZKX),6; 有 個 位 的寄存器( ),使用擴展雙精度格式操作數。當內存中的數據載入數據寄存器時,如果數據格式不是擴展雙精度格式,則在載入過程中進行格式轉換。 個寄存器組成一個循環(huán)堆棧,棧頂保存于狀態(tài)寄存器中,相當于堆 棧指針。每次壓棧(,2* 指令載入數據),堆棧指針就減 ,在 之間循環(huán)。代碼并不直接使用這個指針操作

6、這些寄存器,而是使用 9: d9: 表示。9: 指棧頂,即狀態(tài)寄存器中棧頂指針指示的那個寄存器。假設 當前狀態(tài)寄存器中的棧頂指針是 4(即4 的寄存器位頂),則 9: O 對應的寄存器是:4 O SUJ 例如初始化時狀態(tài)寄存器是 ,,2* 指令裝載了一個數據以后,指針減小 是 ,則 9: 即是寄存器 ,而 9: 對應的寄存器是: SUJ # 這些計算實際上是以 )6; 管理寄存器的方式這 個寄存器組成的堆棧,比較晦澀。式 不是從 )6; 角度理解,而是從指令角度(也就是編程角度)理解,直接將還有9: d9: 看成一個堆棧,9: 是棧頂,每次壓棧,數據向上移動一 個寄存器。例如載入一個數據,這個

7、數據在 9: 中,再次載入一個數據,則當前數據在 9: 中,而上次載入的數據在 9: 中。這種理解方式相對 簡易。 ,6; 寄存器是相對獨立的,不受過程調用的影響。程、進程切換時,操作系統(tǒng)也保存這些寄存器,因此它們也不受線程、進程切換的影響。這意味著這些寄存 器是個存放數據和傳送參數的好地方,例如 的數據寄存器與 ,6; 的數據寄存器名字不同,實際上卻是通過別名機制共用數據寄存器。這意味著,33 指令和 ,6; 指令存在資源共享問題,不可同時使用。 狀態(tài)寄存器(9Y 8KMOYZKX) ,6; 有一個 位寄存器顯示當前的狀態(tài):空閑標志( 位)、條件判斷標志( 位)、數據寄存器堆棧指針( 位)、

8、異常標志( 位)、全局錯誤標志( 位)、堆棧錯誤標志( 位)。一般在一個操作完成以后,通過檢測狀態(tài)寄存 器控制流程。在一般編程中,異常標志和條件標志是最重要的。其他部分僅在出現錯誤時才需要關注,詳情清參閱文獻A C( )指令狀態(tài)寄存器是只讀的,因此與它有關的指令只有一條(但有同步和不同步兩個版本,參見 節(jié)),即 ,9:9=。這條指令將狀態(tài)寄存器中的內容傳送至 寄存器,位次序不變。由于狀態(tài)寄存器共 位,因此正好填滿 。通過檢測 的對應位,即到狀 態(tài)控制器的相關信息,例如前面檢測條件位 ) 的代碼:,9:9=!傳送至 4*+ .!測試 ) # %043?4+: !9: 9: ( )堆棧指 針位 至

9、位 是堆棧指針(共 位),其值在 和 之間循環(huán)。與常規(guī) 指令使用寄存器模式不同,浮點指令使用堆棧模式(更確切地說,是寄存器模式和堆棧 模式的混合),即一般的浮點指令從棧頂取操作數,結果也頂,例如,*6 指令就是如此,它的操作數來自 9: 和 9: ,結果于 9: 。一般情形下,用戶只需保證堆棧不出現錯誤(例如溢出),無需 特別在意它的指針。但在特殊情形下,移動堆棧指針可能有利于提高效率。例如正在進行一個復雜的計算,中間結果占據了多個數據寄存器::56 $假 設當前的堆棧指針位于 JGZG 處,而卻需要計算 YOT JGZG ,那么如何實現呢?常規(guī)方法(不直接操作堆棧指針)代碼:,9:6 JGZ

10、G ,9:6 JGZG ,9:6 JGZG ,9/4 JGZG ,2* JGZG ,2* JGZG ,2* JGZG 如果直接操作堆棧指針(使用 ,/4)9:6 指令),那么:,/4)9:6,/4)9:6,/4)9:6JGZG JGZG JGZG JGZG JGZG JGZG JGZG JGZG ,9/4,*+)9:6,*+)9:6,*+)9:6可以看出,在復雜計算中,常規(guī)方法的代價就是在數據寄存器和內存之間進行多次數據傳送,降低了 執(zhí)行效率,而直接操作堆棧指針可以避免這些。當然,這個例子是編造的,實際代碼可能沒有這么,而且操作堆棧指針相當(清空堆棧時很容易造成堆棧溢出)。除非迫不得已,一般不

11、建議這么做。( )異常位第 章已經提及 /+ 定義了 種異常,每種異常均對應一個位,共 個位。除此而外,還有一個弱規(guī)范數異常,當操作數中出現弱規(guī)范數時,這個異常位就會被設 置(但擴展雙精度格式例外)。在這些硬件基礎上,可以建立兩種異常處理模 式:正常模式和安靜模式。正常的異常處理是硬件觸發(fā)異常,被內核(操作系 統(tǒng)代碼)捕獲,然后由內核傳遞至用戶層,交由指定的異常代碼處理。這種處理模式的特點是,當一切正常、沒有異常觸發(fā)時,異常處理代碼不會被激活,如同不存 在一樣,因此任務代碼執(zhí)行效率較高。但是一旦觸發(fā)了異常,內核代碼和用戶代碼均被激活,處理代碼的執(zhí)行效率較低,系統(tǒng)受到較大干擾。安靜模式就是一切異

12、常,但在任務代碼執(zhí)行過程中,在一些關鍵處(例如結果出來時)進行異常 檢測。如果檢測到異常就進行異常處理,否則繼續(xù)執(zhí)行任務代碼。這種模式即使在異常出現時也不會激活內核代碼,對系統(tǒng)干擾較小,異常處理代碼的效率也高。但 是,大量的檢測代碼即使在沒有異常時也需要運行(否則怎么知道是否發(fā)生異常了呢),從而導致任務代碼效率低下。兩種模式各有優(yōu)缺點,選擇的關鍵在于異常被觸發(fā)的頻率。如果頻率較低,那么正常模式有優(yōu)勢;反 之,安靜模式有優(yōu)勢。幸運的是,在浮點運算中,這兩種模式你都可以根據情形選用。=OTJUY 標準的異常處理模式就是正常模式,常見的ZX_ KIKVZ 塊和ZX_ IGZIN塊就是這種模式在 )

13、) 中的對應物。與此同時,) 的浮點數學庫卻使用安靜模式處理可能出現的異 常,例如如果想處理 GYOT 可能出現的定義域錯誤(操作數學函數異常的一種情形),那么只需提供一個ESGZNKXX 即可。不過這種模式僅用于 ) 的數學函數庫,對普通的浮點代碼無效() 浮點庫沒有提供異常檢測函數)。(4)條件位狀態(tài)寄存器有4個條件位,雖然最常見的用處是給出邏輯比較的結果,但這只是它們在邏輯比較指令中 的作用,在別的指令中,它們還有其他作用,例如在 FXAM 指令中它們給出操作數的類型、在 FPREM 指令中它們返回商的最低3個位。考慮到這些,更確切的 名字應該是指示位。按返回結果方式的不同,x87 FP

14、U 有兩類邏輯比較指令:一類指令直接將結果設置到EFLAGS 寄存器中,例如 FCOM 指令;一類則將結果設置在狀態(tài)寄存器的條件位中,例如FCOMI 指令。兩者在使用上也有差異,例如比較兩個數的大小,使用 FCOMI 指令是:FLDQWORD PTRESIFLDQWORD PTRESI+8FCOMIST(0), ST(1);占用 EFLAGS 部分JBMYNEXT2需要將兩個數都載入寄存器,但檢測結果比較方便。而 FCOM 指令正好相反:FLDQWORD PTRESIFCOMQWORD PTRESI+8FSTSW;占用 AXANDEAX,100H;測試 C0=1?JNZMYNEXT2;ST0

15、ST1只需載入一個即可,但檢測結果比較麻煩,而且會破環(huán) AX。我 喜歡使用 FCOMI 指令(此時無需關心 C0,C1,C2,C3的意義),但在 VC6浮點庫中沒有見到 FCOMI 指令。這里有一個重要的原因,那就是 FCOMI 指令是 P6系列才引入 IA-32體系的,先前的 CPU 不支持。因此,如果需要考慮兼容性,FCOM 指令是唯一的選擇。C0,C1,C2,C3的 意義參見附錄 B 指令說明部分。另一個需要特別注意的細節(jié)是 ,)53/ 指令 的特性,它只設置 +,2-9 寄存器的 ,、), 和 6,,沒有設置 9, 和 5,,因此 ,)53/ 指令的結果類似無符號整型的結果,這意味著緊

16、跟的分支指令應 該使用 0 0+ 0+ 0(+ 0(,而不要使用 0- 0-+ 0+ 02+ 02。否則,結果會出錯。 控制寄存器()UTZXUR 8KMOYZKX)在浮點運算中,需要控制的一般就是計算精度、舍入模式和異常,因此控制寄存器非常簡潔。唯一比猜測多出的是無窮控制位(/TLOTOZ_ )UTZXUR),這是 數學協(xié)處理器的遺跡(我始終沒有弄明白, 數學協(xié)處理器怎么用這個位),在 / 體系中已沒有用處。編寫控制寄存器的操作代碼需要非常一個域,例如 下列代碼:,最常見的錯誤是在一個域時無意中改變了另IUTZXURY # +3E68+)/! 精度異常EEGYS ,2*)= IUTZXURY

17、 設置這段代碼的目的是精度異常,但實際上它也同時清除了對其他異常的以及精度設置和舍入模式 設置。更為麻煩的是,改變精度設置和舍入模式導致的計算精度不夠或錯誤是很難察覺的。避免這種錯誤的基本方法就是對控制寄存器操作提供標準函數,不允許其他代碼操作控制寄存器。參考,更為通用的代碼將在第 章 ) 浮點函數庫中給出。本節(jié)給出的代碼( )指令控制 寄存器可以讀寫,有兩條指令,即載入指令 ,2*)= 和指令 ,9:)=,兩者的操作數均是 位內存單元。代碼示例如下:TYOMTKJ YNUXZ IUTZXURY!EEGYS ,2*)= IUTZXURYEEGYS ,9:)= IUTZXURYEEGYS ,2*

18、)= =58* 6:8 A+96 C( )異常位控制寄存器的低 位用于控制 種異常的作,可以定義一組常量:,設置相應位即可異常。為了方便操 JKLOTK +3E391 , JKLOTK +3E/42/*E56+8:/54 JKLOTK +3E*+45832E56+84* JKLOTK +3E+85E*/*+ JKLOTK +3E5E*5;(2+E 使用擴展雙精度的設置代碼: TYOMTKJ YNUXZ IUTZXURY!EEGYS ,9:)= IUTZXURY 獲取控制寄存器內容IUTZXURY # d6)E391! 清零 否則可能設置錯誤 IUTZXURY b# 6)E+E*5;(2+E !

19、 位 精度EEGYS ,2*)= IUTZXURY 設置( )舍入模式 ,6; 均支持 節(jié)曾式的選擇:的 種舍入模式,控制寄存器的位 和位 控制舍入模同樣可以定 義常量: JKLOTK 8)E391 ) JKLOTK 8)E4+8+9: 舍入模式8)最近舍入 (向 舍入 (向 舍入 (向 舍入(截斷舍入) (精度6)/+ 單精度 位 (保留 (/+ 雙精度 位 (/+ 擴展雙精度 位 ( JKLOTK 8)E*5=4 JKLOTK 8)E;6 JKLOTK 8)E:8;4):+使用最近舍入模式的設置代碼: ) TYOMTKJ YNUXZ IUTZXURY!EEGYS ,9:)= IUTZXUR

20、Y 獲 取控制寄存器內容IUTZXURY # d8)E391! 8) 位清零即是最近舍入EEGYS ,2*)= IUTZXURY 設置 其他寄存器除 了控制寄存器和狀態(tài)寄存器, ,6; 還有幾個寄存器,這些寄存器的主要作用在或調試而非一般編程的接口。于( ) 標志寄存器(:GM 8KMOYZKX)在操作數據寄存器堆棧時,如果寄 存器為空(即沒有初始化過),那么一般浮點指令將出錯;如果寄存器已經有數據,那么 ,2* 指令將出錯。這么規(guī)定的目的是在出現誤操作時通過觸發(fā)異常(堆棧 溢出),避免計算錯誤,提高系統(tǒng)的穩(wěn)定性。但是,僅僅根據數據寄存器的內容(即數據本身)無法判斷該寄存器是否為空,于是就出現

21、了標志寄存器。標記是否為空只需 位,但是每個標記使用了 位,這樣就有 種可能的標記:可見,雖然標記的最初目的是用 于標記是否為空,但兼顧了優(yōu)化計算的目的。除了空之外的 個標記顯然是按計算特性劃分的。一般有限數需要進行計算, 可以快速處理,而特殊值不能參與計 算,只能特殊處理。( )調試寄存器標記說明 一般有限數 特殊值,例如格式、4G4、弱 規(guī)范數 空,即沒有初始化過為 了進一步支持調試, ,6; 還實現了最后指令地址寄存器、最后操作數地址寄存器和操作碼寄存器。浮點計算過程中,當異常被觸發(fā)時,調試最需要知道的自然是哪兒觸發(fā)了這個異常的以及在干什么時觸 發(fā)的。最后指令地址寄存器給出異常指令的地址

22、,如果這條指令使用內存操作數,那么最后操作數地址寄存器給出操作數的內存地址。所給出的地址是 位全局地址,即選擇子 偏移形式,例如 )9 +/6 或 *9 +9/。相關資料 可以參閱文獻A C或 保護模式編程。這些寄存器最可能的用戶是 調試器,一般用戶不大可能編寫指令級異常處理程序,即使是調試錯誤也是在調試器的支持下進行的,因此知道即可,無需關心細節(jié)。 ,6; 指令 指令簡介絕大部分浮點指令都是同步指 令,即當指令返回時,功能已經完成,但有部分控制指令除了同步指令外,還有一個非同步指令的形式,例如狀態(tài)寄存器指令 ,9:9= 就有一個非同步指令 ,49:9=。其實,同步指令實際上是兩條指令,例如

23、,9:9= 指令實際 上是:,=/:,49:9=在 編程的其他領域,有時也有非同步代碼(一般稱異步代碼,例如 =OTO 6/ 的=XOZK,ORK 接口就有異步調用方式),使用它們的主要目的是使的硬件設備并行,從而提高效率,但在 ,6; 編程中,使用非同步指令的主要目的是避免異常檢查。也就是說,同步指令在功能完成即將返回之前會進行異常檢查(即檢查狀態(tài)寄存器的異常位),如果發(fā)現有異常位被設置且控制寄存器對應的異常位沒有設置,那么將觸發(fā)異常,而非同步指令不做這種檢查,因此即使有異常發(fā)生而且沒有被,也不會觸發(fā)異 常。 指令分類 ,6; 指令集大約有近 條指令,下面對這些指令作簡要介紹,更進一步的資料

24、請參閱附錄 浮點指令說明或文獻A C。(1)數據傳 輸指令這些指令類似 x86指令集中的 MOV 指令,它們將數據在數據寄存器 之間、數據寄存器和內存之間進行傳輸。數據格式隨指令不同,可能是浮點數,也可能是整數或 BCD 碼。當源操作數和目的操作數的數據格式不一致時,還會進行 數據格式轉換。某些指令(例如FCMOVcc 指令)有兼容性問題,P6系列以前的 CPU 不支持。(2)常量裝載指令浮點運算中常用到一些常量,例如1.0和 ,x87 FPU 內置了這些數據方便使用。由于數據寄存器使用擴展雙精度格式,因此這些內置數據的精度至少達到了64位的精度。(3)基本算術指令常說的四則運算及其他一些相關

25、指令。不過,不對稱的雙目運算符(例如減法和除法)引入了反向運算,這些指令完成同樣的功能,但參數的位置正 好顛倒了。引入這些指令的目的顯然是減少數據寄存器操作,方便使用。FADD/FADDP/FIADD加法FSUB/FSUBP/FISUB減法FSUBR/FSUBRP/FISUBR反向減法FMUL/FMULP/FIMUL乘法FDIV/FDIVP/FIDIV除法FDIVR/FDIVRP/FIDIVR反向除法FPREM/FPREM1計算部分余數,由于取整不同有兩種。FABS計算絕對值FLD1載入+1.0FLDZ載入+0.0FLDPI載入FLDL2E載入 log2eFLDLN2載入 loge2,即 ln

26、2FLDL2T載入 log210FLDLG2載入 log102FLD/FILD/FBLD將內存或數據寄存器中的數據載入數據堆棧FST/FSTP/FIST/FISTP/FBSTP將 ST(0)中的數據保存到指定的內存或數據寄存器FXCH交換兩個數據寄存器中的內容FCMOVcc滿足條件 cc 則將指定的數據寄存器拷貝到 ST(0)( )比較指令比 較兩個數的大小,即常說的邏輯運算。( )函 數指令計算一些常見的函數值,主要是三角函數、反三角函數和對數函 數。某些函數可能有操作數大小限制(例如 9OTK 函數),即使定義域是整個實數域,需要特別注意。( )控制指令這 些指令控制 ,6; 的各個方面,

27、例如讀寫控制寄存器、讀狀態(tài)寄存器等。,/4)9:6 ,*+)9:6增減堆棧指針,8+清空數據寄存器,/4/: ,4/4/:初始化 ,6;,)2+ ,4)2+清除異常標志,9:)= ,49:)=讀控制寄存器,9/49OTK 函數,)59)UYOTK 函數,9/4)59一次完成 9OTK 函數和)UYOTK 函數的計算,6:4部分正切函數,6:4部分反正切函數, 3 計算 ,?2 計算 _RUM ,?2 6 計算 _RUM 66比較大小,結果在 ) 、) 和 ) 中66比較大小,結果在 ) 、) 和 ) 中6整數比較大小,結果在 ) 、) 和 ) 中/6比較大小,結果在+,2-9 中/6比較大小,

28、結果在+,2-9 中,:9:與 比較,結果在 ) 、) 和 ) 中,3判別數據類型,結果在 ) 、) 和 ) 中,).9改變符號,即計算相反數,84*取整運算,9)2+將操作數放大 的冪次方,例如_ T,978:平方根運算,:8):將浮點數分解為指數和尾數 指令使用( ) 設備初始化初始化硬件只有一條指令 ,/4/:,執(zhí)行 ,/4/: 指令之 后, ,6; 硬件復位??刂萍拇嫫髦凳?,,即所有異常被、最近舍入、 位運算精度。狀態(tài)寄存器清零,即沒有異常、堆棧指針是 。標志寄存器是 ,,即 個數據寄存器中全空,沒有有效數據,但實際上, 個數據寄存器的內容沒有改變。,/4/: 指令在復位硬件前會檢查

29、狀態(tài)寄存器中,如果有異常發(fā)生且控制寄存器沒有該異常則觸發(fā)該異常,,4/4/:的異常狀 態(tài)指令完成與 ,/4/: 一樣的初始化功能,但不進行異常檢測。( )系統(tǒng) 設置,/4/: 指令實際上也作了缺省設置,不過,它的設置可能不符合你的 需要。 ,6;的設置一般有三個方面:異常處理、計算精度和舍入模式,實際上就是控制寄存器的設置。具體操作參見 節(jié)和 節(jié)。狀態(tài)寄存器和標志寄存器是只讀的,一般不會改寫,但可以通過特殊指令改寫(,9+和 ,89:58 指令)。( )計算計算 過程中需要特別注意的是浮點堆棧。由于浮點堆棧不用于程序控制,出了問題以,因此相當隱秘。在 ) ) 后不會立即來,即使來也不一定會導致

30、程序,2*)=寫控制寄存器,9:+4 ,49:+4保存 ,6; 執(zhí)行環(huán)境,不包括數據寄存器,2*+4載入 ,6; 執(zhí)行環(huán)境,不包括數據寄存器,9+ ,49+保存 ,6; 信息,包括數據寄存器,89:58載入 ,6; 信息,包括數據寄存器,9:9= ,49:9=讀狀態(tài)寄存器,=/:等待,456空操作等高級語言編程過程中,編譯器處理了這個問題,但在匯編語言中需要自己處理這個問題。在代碼編寫過程中,要清楚自己使用的數據寄存器內容及個數,一旦不需要就及時清空。數據寄存器只 有 個,因此除非做好了詳細計劃,一般不要使用它們長期數據。減少寄存器使用個數的關鍵在于挑選合適的指令并且安排好指令序列,盡量減少中

31、間結果的個數。例如實現 G H I 的代碼可以是 ,2* G,2* H,2J I,*6 9: 9: ,*6 9: 9: 最多使用了 個數據寄存器,換個形式:,2* G,* H,* I只使用了 個數據寄存器。( )設備信息的現代操作系統(tǒng)多是多用戶系統(tǒng),有多任務(進程或線程)調度功能,用戶任務經常被切換。假設任務 正在進行浮點運算, ,6; 正在執(zhí)行一個指令序列,此時發(fā)生了線程切換,線程 ( 取代線程 獲得了對 ,6; 的控制,線程 ( 自然也可能使用 ,6;,那么顯然線程 的中間結果(正在數據寄存器堆棧中)和設置將被破壞。當線程 再度獲得對 ,6; 的控制時,此時的 ,6; 已是線程 ( 使用時

32、的狀態(tài),線程 的計算將出現錯誤。同樣,線程 ( 也是一團糟。這個問題實際上是個簡單的共享信息問題,解決之道就是在任務切換時進行 信息的保存和恢復,從而使各任務的信息互不干擾。 ,6; 為了支持這一功能,提供了兩條指令,即 ,9+ 指令和 ,89:58 指令。當任務被掛起時,操作系統(tǒng)任務調度模塊使用 ,9+ 指令將 ,6; 保存于任務數據塊中。當任務被恢復時,使用 ,89:58 指令將 ,9+ 指令保存的數據載入 ,6;。如此,計算將不受任務切換的影響。如果你想自己處理浮點異常,那么就需要熟悉 ,9+ 指令保存的信息格式,因為在=OTJUY 中,當異常發(fā)生時,內核正是通過 ,9+ 指令將 ,6;

33、 的信息保存起來傳遞給異常處理代碼。當然,在這個層次處理異常通常是操作系統(tǒng)和浮點庫的任務。除非你想創(chuàng)建一個浮點庫并且該浮點庫完善到自己進行異 常處理,否則你不需要熟悉 ,9+ 指令和,89:58 指令。 代碼示例為測試方便,本節(jié)代碼使用了 ) 的匯編,但使用了 TGQKJ 函數修飾符,盡量匯編的特征。由于 ) )8: 的初始化代碼在程序啟動時就已經初始化了 避免,6; 以支持 JUHRK 類型,而本節(jié)代碼也使精度類型,因此無需再初始化 ,6;,相關的設置也被忽略。實際上,本節(jié)只需注意 ,6; 的指令和寄存器的使用即可。數組求和 ,RUGZ9S 演示基本 的浮點操作,冒泡排序 ,RUGZ9UXZ

34、 演示浮點比較操作,9OTK 函數表 ,RUGZ9OT 演示堆棧管理。所有函數均使用 ) ) 缺省的 EEIJKIR 調用約定,因此返回時無需堆棧。為了盡量減少代碼,所 有函數都沒有進行輸入值檢測等工作,實際代碼應該做這項工作以提高穩(wěn)定性。 數組求和數組求和是非常簡單的常用代 碼:JUHRK ,RUGZ9S JUHRK VJ IUTZ aJUHRK YS # !LUX O # ! OIUTZ! O YS # VJAOC!XKZXT YS!c將上述邏輯轉 換為匯編代碼,除了常規(guī)的循環(huán)控制之外,只使用了 ,2* 和 ,* 兩條浮點指令以及 9: 寄存器。由于 ) 將 9: 作為浮點返回值,因此浮點

35、堆很簡單,幾乎無需注意。代碼如下:棧指針問題也EEJKIRYVKI TGQKJ JUHRK ,RUGZ9S JUHRK VJ IUTZ aEEGYSa6;9.+9/,2* 9: 清 零35+9/ A+96 C VJ35 A+96 C IUTZ3?2556 0+) 3?+/:,*7=58* 6:8 A+9/C 相加*+)+) 計數器*+9/ 地址遞增0363?25563?+/: 656+9/8+: 結 果在 9: 中返回cc 冒泡排序這個程序將給定的數組按從小到大的次序排列,邏輯要復雜一些,) 代碼是:UOJ ,RUGZ9UXZ JUHRK VJ IUTZ aH)UTZOTK # O Q!JUHRK ZKSV!Q # IUTZ!NORK H)UTZOTK aQ !H)UTZOTK # !LUX O# ! OQ! O aOL VJAOC $ VJAO C aZKSV # VJAOC!VJAOC #

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論