Linux內(nèi)核完全剖析---數(shù)學(xué)協(xié)處理器
內(nèi)核目錄kernel/math目錄中包含數(shù)學(xué)協(xié)處理器仿真處理代碼文件,共包含9個C語言程序,見表11-1。本章內(nèi)容與具體硬件結(jié)構(gòu)關(guān)系非常密切,因此需要讀者具備較深的有關(guān)Intel CPU和協(xié)處理器指令代碼結(jié)構(gòu)的知識。但好在這些內(nèi)容與內(nèi)核實現(xiàn)關(guān)系不大,因此跳過本章內(nèi)容并不會妨礙讀者對內(nèi)核實現(xiàn)方法的完整理解。不過若能理解本章內(nèi)容,那么對于實現(xiàn)系統(tǒng)級應(yīng)用程序(例如匯編和反匯編等程序)和編制協(xié)處理器浮點處理程序?qū)⒂泻艽髱椭! ?/P>
11.1 總體功能描述
在計算機上執(zhí)行計算量較大的運算通??梢允褂萌N方法來完成。一種是直接使用CPU普通指令執(zhí)行計算。由于CPU指令是一類通用指令,因此使用這些指令進行復(fù)雜和大量的運算工作需要編制復(fù)雜的計算子程序,并且一般只有通曉數(shù)學(xué)和計算機的專業(yè)人員才能編制出這些子程序。另一種方法是為CPU配置一個數(shù)學(xué)協(xié)處理器芯片。使用協(xié)處理器芯片可以極大地簡化數(shù)學(xué)處理編程難度,并且運算速度和效率也會成倍提高,但需要另外增加硬件投入。還有一種方法是在系統(tǒng)內(nèi)核級使用仿真程序來模擬協(xié)處理器的運算功能。這種方法可能是運算速度和效率最低的一種,但與使用了協(xié)處理器一樣可以方便程序員編制計算程序,并且能夠在對程序不加任何改動的情況下把所編程序運行在具有協(xié)處理器的機器上。
在Linux 0.1x甚至Linux 0.9x內(nèi)核開發(fā)初期,數(shù)學(xué)協(xié)處理器芯片80387(或其兼容芯片)價格不菲,并且一直是普通PC中的奢侈品。因此除非在科學(xué)計算量很大的場合或特別需要之處,一般PC中不會安裝80387芯片。雖然現(xiàn)在的Intel 處理器中都內(nèi)置了數(shù)學(xué)協(xié)處理器功能部件,從而現(xiàn)在的操作系統(tǒng)中已經(jīng)無須包含協(xié)處理器仿真程序代碼,但是因為80387仿真程序完全建立在模擬80387芯片處理結(jié)構(gòu)和分析指令代碼結(jié)構(gòu)基礎(chǔ)上,因此學(xué)習(xí)本章內(nèi)容后讀者不僅能夠了解80387協(xié)處理器編程方法,而且對編寫匯編和反匯編處理程序也有很大幫助。
如果80386 PC中沒有包括80387數(shù)學(xué)協(xié)處理器芯片,那么當CPU執(zhí)行到一條協(xié)處理器指令時就會引發(fā)“設(shè)備不存在”異常中斷7。該異常過程的處理代碼在sys_call.s第158行開始處。如果操作系統(tǒng)在初始化時已經(jīng)設(shè)置了CPU控制寄存器CR0的EM位,那么此時就會調(diào)用math_emulate.c程序中的math_emulate()函數(shù)來用軟件“解釋”執(zhí)行每一條協(xié)處理器指令。
Linux 0.12內(nèi)核中的數(shù)學(xué)協(xié)處理器仿真程序math_emulate.c完全模擬了80387芯片執(zhí)行協(xié)處理器指令的方式。在處理一條協(xié)處理器指令之前,該程序會首先使用數(shù)據(jù)結(jié)構(gòu)等類型在內(nèi)存中建立起一個“軟”80387環(huán)境,包括模仿所有80387內(nèi)部棧式累加器組ST[]、控制字寄存器CWD、狀態(tài)字寄存器SWD和特征字TWD(TAG word)寄存器,然后分析引起異常的當前協(xié)處理器指令操作碼,并根據(jù)具體操作碼執(zhí)行相應(yīng)的數(shù)學(xué)模擬運算。因此在描述math_emulate.c程序的處理過程之前,有必要先介紹一下80387的內(nèi)部結(jié)構(gòu)和基本工作原理。
11.1.1 浮點數(shù)據(jù)類型
本節(jié)主要介紹協(xié)處理器使用的浮點數(shù)據(jù)類型。首先簡單回顧一下整型數(shù)的幾種表示方式,然后說明浮點數(shù)的幾種標準表示方式以及在80387中運算時使用的臨時實數(shù)表示方法。
1.整型數(shù)據(jù)類型
對于Intel 32位CPU來講,有三種基本無符號數(shù)據(jù)類型:字節(jié)(byte)、字(word)和雙字(double word),分別有8、16和32位。無符號數(shù)的表示方式很簡單,字節(jié)中的每個位都代表一個二進制數(shù),并且根據(jù)其所處位置具有不同的權(quán)值。例如一個無符號二進制數(shù)0b10001011可表示為:
U = 0b10001011 = 1×27 + 0×26 + 0×25 + 0×24 + 1×23 + 0×22 + 1×21 + 1×20 = 139
它對應(yīng)十進制數(shù)139。其中權(quán)值最小的一位(20)通常被稱為最低有效位(LSB,Least Significant Bit),而權(quán)值最大的位(27)被稱為最高有效位(MSB,Most Significant Bit)。
#p#而計算機中具有負數(shù)值的整型數(shù)據(jù)表示方法通常也有三種:2的補碼(Two’s complement)、符號數(shù)(Sign magnitude)和偏置數(shù)(biased number)表示方式。表11-2給出了這三種形式表示的一些數(shù)值。
2的補碼(二進制補碼)表示法是目前大多數(shù)計算機CPU使用的整數(shù)表示方法,因為CPU的無符號數(shù)的簡單加法也適用于這種格式的數(shù)據(jù)運算。使用這種表示法,一個數(shù)的負數(shù)就是該數(shù)每位取反后再加1。MSB位就是該數(shù)的符號位。MSB= 0表示一個正數(shù);MSB = 1表示負數(shù)。80386 CPU具有8位(1字節(jié))、16位(1字)和32位(雙字)2的補碼數(shù)據(jù)類型,分別可以表示的數(shù)據(jù)范圍是:-128~127、-32768~32767、-2147483648~2146473647。另外,在80387仿真程序中使用了一種稱為臨時整數(shù)類型的格式,如圖11-1所示。它的長度為10字節(jié),可表示64位整型數(shù)據(jù)類型。其中低8字節(jié)最大可表示63位無符號數(shù),而最高2字節(jié)僅使用了最高有效位來表示數(shù)值的正負。對于32位整型值則使用低4字節(jié)來表示,16位整型值則使用低2字節(jié)表示。
數(shù)的偏置表示法通常用于表示浮點數(shù)格式中的指數(shù)字段值。把一個數(shù)加上指定的偏置值就是該數(shù)的偏置數(shù)表示的值。從表11-1可以看出,這種表示方法的數(shù)值具有無符號數(shù)的大小順序。因此這種表示方法易于比較數(shù)值大小。即大數(shù)值的偏置表示值總是無符號值的一個大數(shù),而其他兩種表示方式卻并非如此。
符號數(shù)表示法有一個位專門用于表示符號(0表示正數(shù),1表示負數(shù)),而其他位則與無符號整數(shù)表示的數(shù)值相同。浮點數(shù)的有效數(shù)(尾數(shù))部分使用的就是這種表示方法,而符號位代表整個浮點數(shù)的正負符號。
2.BCD碼數(shù)據(jù)類型
BCD(Binary Coded Decimal)碼數(shù)值是二進制編碼的十進制數(shù)值,對于壓縮的BCD編碼,每個字節(jié)可表示兩位十進制數(shù),其中每4位表示一位0~9的數(shù)。例如,十進制數(shù)59的壓縮BCD碼表示是0x01011001。對于非壓縮的BCD碼,每個字節(jié)只使用低4位表示1位十進制數(shù)。
80387協(xié)處理器支持10字節(jié)壓縮BCD碼的表示和運算,可表示18位十進制數(shù),如圖11-2所示。與臨時整數(shù)格式類似,其中最高字節(jié)僅使用了符號位(最高有效位)來表示數(shù)值的正負,其余位均不用。若BCD碼數(shù)據(jù)是負數(shù),則會使用最高地址處1字節(jié)的最高有效位置1來表示負值。否則最高字節(jié)所有位均是0。
#p#3.浮點數(shù)據(jù)類型
具有整數(shù)部分和小數(shù)(尾數(shù))部分的數(shù)稱為實數(shù)或浮點數(shù)。實際上整型數(shù)是小數(shù)部分為0的實數(shù),是實數(shù)集的一個子集。由于計算機使用固定長度位來表示一個數(shù),因此并不能精確地表示所有實數(shù)。由于計算機表示實數(shù)時為了在固定長度位內(nèi)能表示盡量精確的實數(shù)值,分配給表示小數(shù)部分的位個數(shù)并不是固定的,即小數(shù)點是可以“浮動”的,因此計算機表示的實數(shù)數(shù)據(jù)類型也稱為浮點數(shù)。為了便于程序移植,目前計算機中都使用IEEE標準754指定的浮點數(shù)表示方式來表示實數(shù)。
這種實數(shù)表示方式的一般格式如圖 11-3 所示。它由有效數(shù)(Significant)部分、指數(shù)(Exponent)部分和符號位(Sign)組成。80387協(xié)處理器支持三種實數(shù)類型,它們每個部分使用的位數(shù)如圖11-4所示。
其中S是一個位的符號位。S=1表示是負實數(shù);S=0表示是正實數(shù)。有效數(shù)(Significant)給出了實數(shù)數(shù)值的有效位數(shù)或尾數(shù)。當使用指數(shù)時,一個實數(shù)可以表示成多種形式。例如十進制數(shù)字10.34可以表示成1034.0×10-2、10.34×100、1.034×101或0.1034×102等。為了使計算能夠得到最大精度值,我們總是對實數(shù)進行規(guī)格化(Normalize)處理,即調(diào)整實數(shù)的指數(shù)值,使得二進制最高有效數(shù)值總是1,并且小數(shù)點就位于其右側(cè)。因此,上述例子正確的規(guī)格化處理結(jié)果就是1.034×101。對于二進制數(shù)來說就是1.XXXXX×2N(其中X是1或0)。如果我們總是使用這種形式來表示一個實數(shù),那么小數(shù)點左邊肯定是1。所以在80387的短實數(shù)(單精度)和長實數(shù)(雙精度)格式中,這個“1”就沒有必要明確地表示出來。因此在短實數(shù)或長實數(shù)的二進制有效數(shù)中,0x0111...010實際上就是0x1.0111...010。
格式中的指數(shù)字段含有把一個數(shù)表示成規(guī)格化形式時所需要的2的冪次值。正如前面提到的,為了便于數(shù)字大小的比較,80387使用偏置數(shù)形式來存儲指數(shù)值。短實數(shù)、長實數(shù)和臨時實數(shù)的偏置基量分別是127、1023和16383。因此一個短實數(shù)指數(shù)值0b10000000實際表示21(0b01111111 + 0b00000001)。
另外,臨時實數(shù)是80387內(nèi)部運算時表示數(shù)的格式。它的最高有效數(shù)1被明確地放置在位63處,并且無論你給出的數(shù)是什么數(shù)據(jù)類型的(例如,整型數(shù)、短實數(shù)或BCD碼數(shù)等),80387都會把它轉(zhuǎn)換成臨時實數(shù)格式。80387這樣做的目的是為了使得精度最大化并且盡量減少運算過程中的溢出異常。顯式地把1表示出來是因為80387在運算過程中確實需要該位(用于表示極小的數(shù)值)。當輸入到80387中的短型或長型實數(shù)被轉(zhuǎn)換成臨時實數(shù)格式時,就會明確地在位63處放置一個1。
4.特殊實數(shù)
與上面表中格式某些值無法表示的情況類似,使用實數(shù)格式表示的某些值也有其特殊含義。對于80位長度格式的臨時實數(shù),80387并沒有使用其可表示的所有范圍數(shù)值。表11-3是80387使用中的臨時實數(shù)所能表示的所有可能的數(shù)值,其中有效數(shù)一欄虛線左側(cè)1位表示臨時實數(shù)位63,即明確表示數(shù)值1的位。短實數(shù)和長實數(shù)沒有此位,因此也沒有表中的偽非規(guī)格化類別。下面說明其中的一些特殊值:零值、無窮值、非規(guī)格化值、偽非規(guī)格化值以及信號NaN(Not a Number)和安靜NaN。
零是指數(shù)和有效數(shù)均為0的值,其余指數(shù)為0的值作保留,即指數(shù)是0的值不能表示一個正常實數(shù)值。無窮值是指數(shù)值為全1、有效數(shù)值為全零的值,而且指數(shù)值為0x11...11的所有其余值也作保留使用。
#p#非規(guī)格化數(shù)(Denormals)是一種用于表示非常小數(shù)值的特殊類值。它可以表示漸進下溢或漸進精度丟失情況。通常要求數(shù)值表示成規(guī)格化數(shù)(左移直到有效數(shù)的最高有效位是位1)。然而非規(guī)格化數(shù)的有效數(shù)最高有效位不是1。此時偏置型指數(shù)0x00...00分別是值為2-126、2-1022、2-16382的短實數(shù)、長實數(shù)和臨時實數(shù)指數(shù)值的特殊表示方式。這種表示比較特殊,因為偏置型指數(shù)0x00...01對三種實數(shù)類型也分別表示相同的指數(shù)值2-126、2-1022、2-16382。
偽非規(guī)格化類數(shù)值(Pseudo-denormals)是有效數(shù)最高有效位為1的值,而非規(guī)格化類數(shù)值的該位是0。偽非規(guī)格化數(shù)很少見,它們可以用規(guī)格化類數(shù)來表示卻沒有這么做。因為上面已經(jīng)說明特殊的偏置指數(shù)0x00...00與規(guī)格化數(shù)的指數(shù)0x00...01具有相同的值。因此偽非規(guī)格化類數(shù)可以表示成規(guī)格化類數(shù)值。
另一種特殊情況是NaN。NaN是指“不是一個數(shù)”(Not a Number)。NaN有兩種形式:會產(chǎn)生信號(Signaling)的和不會產(chǎn)生信號的或稱為安靜的(Quiet)。當一個產(chǎn)生信號的NaN(SNaN)被用于操作時就會引發(fā)一個無效操作異常,而一個安靜的NaN(QNaN)則不會。SnaN是一類會引發(fā)無效操作異常的數(shù)值。使用的方法就是程序先把變量都初始化為SNaN值,在實際使用這個變量時還需要對其進行真正的賦值。這樣若操作過程中使用了一個未被初始化的值就會引發(fā)異常。當然,NaN類數(shù)值也可以用來存儲其他信息。
80387自身不會產(chǎn)生SNaN類的值,但會產(chǎn)生QNaN類的值。當發(fā)生無效操作異常時80387就會產(chǎn)生一個QNaN類值,并且操作的結(jié)果將是不確定值(Indefinite)。不確定值是一種特殊的QNaN類值。每種數(shù)據(jù)類型都有一個表示不確定值的數(shù)。對于整型數(shù)則是用其最大負數(shù)來表示其不確定值。
另外還有一些80387不支持的臨時實數(shù)值,即那些沒有在上表中列出的數(shù)值范圍。若80387遇到這些數(shù)值,就會引發(fā)無效操作異常。
11.1.2 數(shù)學(xué)協(xié)處理器功能和結(jié)構(gòu)
80386雖然是一個通用微處理器,但其指令并不是非常適用于數(shù)學(xué)計算。因此若使用80386來執(zhí)行數(shù)學(xué)計算,那么就需要編制非常復(fù)雜的程序,而且執(zhí)行效率也相對較低。80387作為80386的輔助處理芯片,極大地擴展了程序員的編程范圍。以前程序員不太可能做到的事,使用協(xié)處理器后就可以很容易地,并且快速而精確地完成。
80387具有一組特別的寄存器。這組寄存器可以讓80387直接操作比80386所能處理的大或小幾個數(shù)量級的數(shù)值。80386使用2進制補數(shù)方式表示一個數(shù)。這種方法不適合用來表示小數(shù)。而80387并不使用2的補數(shù)方法來表示數(shù)值,它使用了IEEE標準754規(guī)定的80位(10個字節(jié))格式。這種格式不僅具有廣泛的兼容性,而且能夠使用二進制表示極大(或極小)的數(shù)值。例如,它能表示大到1.21×104932數(shù)值,也能處理小到3.3×10-4932的數(shù)。80387并不保持固定小數(shù)點的位置,如果數(shù)值小的話就多使用一些小數(shù)位,如果數(shù)值大的話就少用幾位小數(shù)位。因此小數(shù)點的位置是可以“浮動”的。這也是術(shù)語“浮點”數(shù)的由來。
為支持浮點運算,80387中包含三組寄存器,如圖11-5所示。① 8個80位長的數(shù)據(jù)寄存器(累加器),可用于臨時存放8個浮點操作數(shù),并且這些累加器可以執(zhí)行棧式操作;② 3個16位狀態(tài)和控制寄存器:一個狀態(tài)字寄存器SWD、一個控制字寄存器CWD和一個特征(TAG)寄存器;③ 4個32位出錯指針寄存器(FIP、FCS、FOO和FOS)用于確定導(dǎo)致80387內(nèi)部異常的指令和內(nèi)存操作數(shù)。
#p#
1.棧式浮點累加器
在浮點指令執(zhí)行過程中,8個80位長度的物理寄存器組被作為棧式累加器使用。雖然每個80位寄存器有固定的物理順序位置(即左邊的0~7),但當前棧頂則由ST(即ST(0))來指明。ST之下的其余累加器使用名稱ST(i)來指明(i = 1~7)。至于哪個80位物理寄存器是當前棧頂ST,則由具體操作過程指定。在狀態(tài)字寄存器中名稱為TOP的3位字段含有當前棧頂ST對應(yīng)的80位物理寄存器的絕對位置。一個入棧(Push)操作將會把TOP字段值遞減1,并把新值存儲于新的ST中。在入棧操作之后,原來的ST變成了ST(1),而原來的ST(7)變成了現(xiàn)在的ST。即所有累加器的名稱都從原來的ST(i)變成了ST((i+1)&0x7)。一個出棧(Pop)操作將會讀出當前ST對應(yīng)的80位寄存器的值,并且把TOP字段值遞增1。因此在出棧操作之后,原來的ST(即ST(0))變成了ST(7),原來的ST(1)成為新的ST。即所有累加器的名稱都從原來的ST(i)變成ST((i-1)& 0x7)。
ST的作用如同一個累加器是因為它被作為所有浮點指令的一個隱含操作數(shù)。若有另一個操作數(shù),那么該第2個操作數(shù)可以是任何其余累加器之一ST(i),或者是一個內(nèi)存操作數(shù)。棧中的每個累加器為一個實數(shù)提供了使用臨時實數(shù)格式存儲的80位空間,其最高位(s)是符號位,位78~64是15位的指數(shù)字段,位63~0是64位的有效數(shù)字段。
浮點指令被設(shè)計成能充分利用這個累加器棧模式。浮點加載指令(FLD等)會從內(nèi)存中讀取一個操作數(shù)并壓入棧中,而浮點存儲指令則會從當前棧頂取得一個值并寫到內(nèi)存中。若棧中該值不再需要時還可以同時執(zhí)行出棧操作。加和乘之類的操作會把當前ST寄存器內(nèi)容作為一個操作數(shù),而另一個取自其他寄存器或內(nèi)存中,并且在計算完后即把結(jié)果保存在ST中。還有一類“操作并彈出”操作形式用于在ST和ST(1)兩者之間進行運算。這種操作形式會執(zhí)行一次彈出操作,然后把結(jié)果放入新的ST中。
2.狀態(tài)與控制寄存器
三個16位的寄存器(TAG字、控制字和狀態(tài)字)控制著浮點指令的操作并且為其提供狀態(tài)信息。它們的具體格式如圖11-6所示。下面逐一對它們進行說明。
(1)控制字
控制字(Control Word)可用于程序設(shè)置各種處理選項來控制80387的操作。其中可分為三個部分。位11~10的RC(Rounding Control)是舍入控制字段,用于對計算結(jié)果進行舍入操作。位9~8的PC(Precision Control)是精度控制字段,用于在保存到指定存儲單元之前對計算結(jié)果進行精度調(diào)整。所有其他操作使用臨時實數(shù)格式精度,或者使用指令指定的精度。位5~0是異常屏蔽位,用于控制協(xié)處理器異常處理。這6位對應(yīng)80387可能發(fā)生的6種異常情況。其中每一種異常都可以單獨屏蔽掉。如果發(fā)生某個特定異常并且其對應(yīng)屏蔽位沒有置位,那么80387就會向CPU通報這個異常,并且會讓CPU產(chǎn)生異常中斷int 16。然而如果設(shè)置了對應(yīng)屏蔽位,那么80387就會自己處理并糾正發(fā)生的異常問題而不會通知CPU。這個寄存器隨時可以讀寫,其中各位的具體含義參見圖11-6。
(2)狀態(tài)字
在運行期間,80387會設(shè)置狀態(tài)字(Status Word)中的位,用于程序檢測特定的條件。當發(fā)生異常時,它可讓CPU確定發(fā)生異常的原因。因為所有6個協(xié)處理器異常都會讓CPU產(chǎn)生異常中斷int16。
(3)特征字
特征字(Tag Word)寄存器含有8個2位的Tag字段,分別對應(yīng)8個物理浮點數(shù)據(jù)寄存器。這些特征字段分別指明相應(yīng)的物理寄存器含有有效、零、特殊浮點數(shù)值,或者是空的。特殊數(shù)值是指那些無限值、非數(shù)值、非規(guī)格化或不支持格式的數(shù)值。特征字段Tag可用于檢測累加器堆棧上下溢出情況。如果入棧(Push)操作遞減TOP指向了一個非空寄存器,就會發(fā)生棧上溢出。如果出棧(Pop)操作企圖去讀取或彈出空寄存器,就會造成棧下溢出(Underflow)。棧的上下溢出都將引發(fā)無效操作異常。
#p#3.出錯指針寄存器
出錯指針寄存器(Error-Pointer Register)是4個32位的80387寄存器,其中含有80387最后執(zhí)行指令和所用數(shù)據(jù)的指針,參見圖11-6。前兩個寄存器FIP和FCS中是最后執(zhí)行指令中2個操作碼的指針(忽略前綴碼)。FCS是段選擇符和操作碼,F(xiàn)IP是段內(nèi)偏移值。后兩個寄存器FOO和FOS是最后執(zhí)行指令內(nèi)存操作數(shù)的指針。FOS中是段選擇符,F(xiàn)OO中是段內(nèi)偏移值。如果最后執(zhí)行的協(xié)處理器指令不含內(nèi)存操作數(shù),則后兩個寄存器值無用。指令FLDENV、FSTENV、FNSTENV、FRSTOR、FSAVE和FNSAVE用于加載和保存這4個寄存器的內(nèi)容。前3條指令共加載或保存28字節(jié)內(nèi)容:控制字、狀態(tài)字和特征字以及4個出錯指針寄存器??刂谱帧顟B(tài)字和特征字都以32位操作,高16位為0。后3條指令用于加載或保存協(xié)處理器所有108字節(jié)的寄存器內(nèi)容。
4.浮點指令格式
對協(xié)處理器進行仿真就是解析具體的浮點指令操作碼和操作數(shù),根據(jù)每一條指令的結(jié)構(gòu)使用80386的普通指令來執(zhí)行相應(yīng)的仿真操作。數(shù)學(xué)協(xié)處理器80387共有七十多條指令,共分5類,見表11-4。每條指令的操作碼都有2個字節(jié),其中第一個字節(jié)高5位都是二進制11011。這5位的數(shù)值(0x1b或十進制27)正好是字符ESC(轉(zhuǎn)義)的ASCII代碼值,因此所有數(shù)學(xué)協(xié)處理器指令都被形象地稱為ESC轉(zhuǎn)義指令。在仿真浮點指令時可忽略相同的ESC位,只要判斷低11位的值即可。
表中各個字段的含義如下(有關(guān)這些字段的具體含義和詳細說明請參考80x86處理器手冊):
1)OP(Operation opcode)是指令操作碼,在有些指令中它被分成了OPA和OPB兩部分。
2)MF(Memory Format)是內(nèi)存格式。00:32位實數(shù);01:32位整數(shù);10:64位實數(shù);11:64位整數(shù)。
3)P(Pop)指明在操作后是否要執(zhí)行一次出棧處理。0:不需要;1:操作后彈出棧。
4)d(destination)指明保存操作結(jié)果的累加器。0:ST(0);1:ST(i)。
5)MOD(Mode)和R/M(Register/Memory)是操作方式字段和操作數(shù)位置字段。
6)SIB(Scale Index Base)和DISP(Displacement)是具有MOD和R/M字段指令的可選后續(xù)字段。
另外,所有浮點指令的匯編語言助記符都以字母F開頭,例如:FADD、FLD等。還有如下一些標準表示方法:
1)FI 所有操作整型數(shù)據(jù)的指令都以FI開頭,例如FIADD、FILD等。
2)FB 所有操作BCD類型數(shù)據(jù)的指令都以FB開頭,例如FBLD、FBST等。
3)FxxP 所有會執(zhí)行一次出棧操作的指令均以字母P結(jié)尾,例如FSTP、FADDP等。
4)FxxPP 所有會執(zhí)行二次出棧操作的指令均以字母PP結(jié)尾,例如FCOMPP、FUCOMPP等。
5)FNxx 除了以FN開頭的指令,所有指令在執(zhí)行前都會先檢測未屏蔽的運算異常。而以FN開頭的指令不檢測運算異常情況,例如FNINIT、FNSAVE等。