這一章講述了匯編語言指令語法和功能。更多的技術(shù)信息可以閱讀Intel軟件開發(fā)者手冊。 匯編指令有助記符(指令名稱)和0到3個操作符組成。如果有大于兩個的操作符,通常第一個為目的操作符第二個為源操作符。每個操作符都可以為寄存器,內(nèi)存或立即數(shù)(操作符語法見1.2節(jié))。每條指令描述后悔有操作符不同用法的例子。 一些指令用作前綴,可以和其他指令放在同行一起使用,一行也允許有多個前綴。段寄存器也是指令助記符前綴,但推薦在方括號中段重寫來替代這些前綴。 mov從源操作符傳送字節(jié),字或雙字道目的操作符。它可以在通用寄存器之間,通用寄存器到內(nèi)存,或從內(nèi)存到通用寄存器間傳送數(shù)據(jù),但不能在內(nèi)存間傳送數(shù) 據(jù)。它也可以在立即數(shù)到通用寄存器或內(nèi)存,段寄存器到通用寄存器或內(nèi)存,通用寄存器或內(nèi)存到段寄存器,控制或調(diào)試寄存器到通用寄存器以及通用寄存器到控制 或調(diào)試寄存器間傳送數(shù)據(jù)。只有當(dāng)源操作符和目的操作符大小相同時mov才能被匯編。下面是一些例子:
mov bx,ax ; 通用寄存器到通用寄存器 mov [char],al ; 通用寄存器到內(nèi)存 mov bl,[char] ; 內(nèi)存到通用寄存器 mov dl,32 ; 立即數(shù)到通用寄存器 mov [char],32 ; 立即數(shù)到內(nèi)存 mov ax,ds ; 段寄存器到通用寄存器 mov [bx],ds ; 段寄存器到內(nèi)存 mov ds,ax ; 通用寄存器到段寄存器 mov ds,[bx] ; 內(nèi)存到段寄存器 mov eax,cr0 ; 控制寄存器到通用寄存器 mov cr3,ebx ; 通用寄存器到控制寄存器 xchg置換兩個操作數(shù)內(nèi)容。它可以用來置換兩個字節(jié)、字或者雙字操作數(shù)。操作數(shù)的順序并不重要。操作數(shù)可以為兩個通用寄存器,或者通用寄存器同內(nèi)存。例如: xchg ax,bx ; 置換兩個通用寄存器 xchg al,[char] ; 寄存器和內(nèi)存置換 push遞減堆棧指針(esp寄存器),然后傳送操作數(shù)到esp執(zhí)行的棧頂。操作數(shù)可以為內(nèi)存,通用寄存器,段寄存器或字、雙字立即數(shù)。如果操作數(shù) 為沒有指定大小的立即數(shù)時,匯編器在16位模式下默認(rèn)將當(dāng)作16位值,在32位模式下將當(dāng)作32位值。pushw和pushd助記符為push指令的變 種,分別用來壓入16位,32位大小值到堆棧。如果同行后指定了更多參數(shù)(空格分隔,而非逗號),將匯編為一串push指令。下面為帶有單一操作符的例 子: push ax ; 壓入通用寄存器到堆棧 push es ; 壓入段寄存器 pushw [bx] ; 壓入內(nèi)存值 push 1000h ; 壓入立即數(shù) pusha壓入8個通用寄存器的內(nèi)容到堆棧,這條指令沒有操作數(shù)。這條指令有兩個版本,一個16位的和一個32位的,匯編器自動根據(jù)當(dāng)前模式生成正 確的版本,但也可以使用pushaw或pushad助記符重寫為只為16位或32位版本。16位版本的這條指令將以以下順序壓入通用寄存 器:ax,cx,dx,bx,壓入ax前的sp值,bp,si和di。32為版本將以相同順序壓入等價的32位通用寄存器。 pop傳送當(dāng)前棧頂?shù)淖只螂p字到目的操作符,然后遞增esp指向新的棧頂。操作符可以為內(nèi)存,通用寄存器或段寄存器。popw和popd助記符為pop指令的變種,分別用來彈出字或雙字。如果同行后指定了更多參數(shù)(空格分隔,而非逗號)將匯編為一串pop指令。 pop bx ; 彈出棧頂數(shù)據(jù)到通用寄存器 pop ds ; 彈出到段寄存器 popw [si] ; 彈出到內(nèi)存 popa彈出堆棧中由pusha指令壓入的寄存器,將忽略其中保存的sp(或esp)值。使用popaw或popad助記符來強(qiáng)制匯編16位或32位版本的這條指令。 2.1.2 類型轉(zhuǎn)換指令類型轉(zhuǎn)換指令轉(zhuǎn)換字節(jié)為字,字為雙字,雙字為四字。這些轉(zhuǎn)換可以為符號擴(kuò)展或零擴(kuò)展的。符號擴(kuò)展將用符號位來填充,而零擴(kuò)展將使用0來填充。 cwd和cdq分別用來擴(kuò)展ax和eax大小,并將額外位存儲到dx和edx中。轉(zhuǎn)換將使用符號擴(kuò)展。這些指令沒有操作數(shù)。 cbw符號擴(kuò)展al的值到ax,cwde符號擴(kuò)展ax到eax。這些指令也沒有操作數(shù)。 movsx使用符號擴(kuò)展將字節(jié)轉(zhuǎn)換為字或雙字,字轉(zhuǎn)換為雙字。movzx類似,只是它使用0擴(kuò)展。源操作數(shù)可以為通用寄存器或內(nèi)存,目的操作數(shù)必須為通用寄存器。例如: movsx ax,al ; 字節(jié)寄存器轉(zhuǎn)換為字寄存器 movsx edx,dl ; 字節(jié)寄存器轉(zhuǎn)換為雙字寄存器 movsx eax,ax ; 字寄存器轉(zhuǎn)換為雙字寄存器 movsx ax,byte [bx] ; 字節(jié)內(nèi)存之后為字寄存器 movsx edx,byte [bx] ; 字節(jié)內(nèi)存轉(zhuǎn)換為雙字寄存器 movsx eax,word [bx] ; 字內(nèi)存轉(zhuǎn)換為雙字寄存器 2.1.3 二進(jìn)制算術(shù)指令add替換目的操作數(shù)的值為源操作數(shù)和目的操作數(shù)的和,并且在溢出時設(shè)置CF標(biāo)志。操作數(shù)可以為字節(jié),字或雙字。目的操作數(shù)可以為通用寄存器或內(nèi)存,源操作數(shù)可以為通用寄存器或立即數(shù),如果目的操作數(shù)為寄存器也可以為內(nèi)存。 add ax,bx ; add 寄存器到寄存器 add ax,[si] ; add 內(nèi)存到寄存器 add [di],al ; add 寄存器到內(nèi)存 add al,48 ; add 立即數(shù)到寄存器 add [char],48 ; add 立即數(shù)到內(nèi)存 adc和add類似,只是如果設(shè)置CF的話結(jié)果還將遞增1。add后跟著多個adc指令能用來計(jì)算大于32位值的和。 inc將操作數(shù)值遞增1,它不影響CF。操作數(shù)可以為通用寄存器或內(nèi)存,操作數(shù)大小可以為字節(jié),字或雙字。 inc ax ; 寄存器值遞增1 inc byte [bx] ; 內(nèi)存值遞增1 sub用目的操作數(shù)值減去源操作數(shù),并且用結(jié)果替換目的操作數(shù)。如果需要借位,將設(shè)置CF。操作數(shù)規(guī)則和add指令相同。 sbb和sub類似,只是如果設(shè)置CF的話結(jié)構(gòu)還將遞減1。操作數(shù)規(guī)則和add質(zhì)量相同。sub后跟著多個sbb指令能用來計(jì)算大于32位值的差。 dec將操作數(shù)值遞減1,它不影響CF。操作數(shù)規(guī)則和inc指令相同。 cmp用目的操作數(shù)減去源操作數(shù),類似sub指令更新標(biāo)志值,但它不改變源和目的操作符。操作數(shù)規(guī)則和sub指令相同。 neg用0減去帶符號的整數(shù)操作數(shù)。這條指令的效果是將帶符號的操作數(shù)從正數(shù)變?yōu)樨?fù)數(shù)或者從負(fù)數(shù)變?yōu)檎龜?shù)。操作數(shù)規(guī)則和inc指令相同。 xadd交換目的和源操作數(shù),然后載入兩個值的和到目的操作數(shù)。操作數(shù)規(guī)則和add指令相同。 所有上面的二進(jìn)制算術(shù)指令都將更新SF,ZF,PF和OF標(biāo)志。SF被設(shè)置為結(jié)果符號位的值,ZF當(dāng)結(jié)果為0時設(shè)置為1,PF當(dāng)?shù)?位存在偶數(shù)個1時設(shè)置,OF在結(jié)果對于正數(shù)太大或?qū)τ谪?fù)數(shù)太?。ǔ^符號位)以放到目的操作數(shù)中時設(shè)置。 mul計(jì)算無符號操作數(shù)和累加器的積。如果為8位操作數(shù),將和al計(jì)算積,16位結(jié)果返回到ah和al中。如果4,為16位操作數(shù),將和ax計(jì)算 積,32位結(jié)果返回到dx和ax中。如果為32位操作數(shù),將和eax計(jì)算積,64位結(jié)果返回到edx和eax中。當(dāng)結(jié)果高半部分不為零時將設(shè)置標(biāo)志CF和 OF,否則將清除該標(biāo)志。操作數(shù)規(guī)則和inc指令相同。 imul執(zhí)行符號乘法運(yùn)算。這條指令有3種用法。第一種允許一個操作數(shù),和mul指令類似。第二種有兩個操作數(shù),此時將計(jì)算目的操作數(shù)和源操作數(shù)的 積,并將結(jié)果替換目的操作數(shù)。目的操作數(shù)可以為16位或32位通用寄存器,源操作數(shù)可以為通用寄存器,內(nèi)存或立即數(shù)。第三種有3個操作數(shù),目的操作數(shù)必須 為16位或32位通用寄存器,源操作數(shù)可以為通用寄存器或內(nèi)存,第三種操作數(shù)必須為立即數(shù)。源操作數(shù)乘以立即數(shù)并將結(jié)果保存到目的寄存器。所有上面三種形 式都將計(jì)算出雙倍大小的結(jié)構(gòu),并當(dāng)結(jié)果高半部分不為零時設(shè)置標(biāo)志CF和OF。所以第二種和第三種形式也能用作無符號操作數(shù),因?yàn)椋瑹o論操作數(shù)是否為有符號 無符號,結(jié)果的低半部分是相同的。下面的所有三種形式的乘法指令使用例子: imul bl ; 累加器和寄存器 imul word [si] ; 累加器和內(nèi)存 imul bx,cx ; 寄存器和寄存器 imul bx,[si] ; 寄存器和內(nèi)存 imul bx,10 ; 寄存器和立即數(shù) imul ax,bx,10 ; 寄存器,立即數(shù),值到寄存器 imul ax,[si],10 ; 內(nèi)存,立即數(shù),值到寄存器 div計(jì)算操作數(shù)和累加器無符號運(yùn)算的商。被除數(shù)(累加器)為兩倍大小的除數(shù)(操作數(shù)),商和余數(shù)和除數(shù)有相同尺寸。如果除數(shù)為8位,被除數(shù)為 ax,商和余數(shù)分別保存到al和ah中。如果除數(shù)為16位,被除數(shù)的商的高半部分從dx獲取,低半部分從ax獲取,商和余數(shù)分別保存到ax和dx中。如果 除數(shù)為32位,被除數(shù)的高半部分從edx獲取,低半部分從eax獲取,商和余數(shù)分別保存到eax和edx中。操作數(shù)規(guī)則和mul指令相同。 idiv計(jì)算操作數(shù)和累加器有符號運(yùn)算的商。它使用和div指令相同的寄存器,操作數(shù)的規(guī)則也是一樣的。 2.1.4 十進(jìn)制算術(shù)指令十進(jìn)制算術(shù)指令用來調(diào)整上一節(jié)的二進(jìn)制算術(shù)操作以生成有效的壓縮或未壓縮十進(jìn)制結(jié)果,或調(diào)整輸入為一個二進(jìn)制算術(shù)操作序列以使該操作能生產(chǎn)一個有效的壓縮或解壓縮十進(jìn)制結(jié)果。 daa調(diào)整al中兩個有效壓縮十進(jìn)制操作數(shù)和的值。daa必須跟著兩對壓縮十進(jìn)制數(shù)(每半字節(jié)一個點(diǎn))的和來得到一對有效壓縮十進(jìn)制數(shù)字結(jié)果。如果需要進(jìn)位將設(shè)置CF標(biāo)志。這條指令沒有操作數(shù)。 das調(diào)整al中兩個有效壓縮十進(jìn)制操作數(shù)差的值。das必須跟著兩對壓縮十進(jìn)制數(shù)(每半個字節(jié)一個點(diǎn))的差來得到一對有效壓縮十進(jìn)制數(shù)字結(jié)果。如果如要進(jìn)位將設(shè)置CF標(biāo)志。這條指令沒有操作數(shù)。 aaa修改al中的內(nèi)容為有效的未壓縮十進(jìn)制數(shù)字,并將高四位清零。aaa必須跟著al中兩個有效未壓縮十進(jìn)制操作數(shù)和。如果需要進(jìn)位將設(shè)置CF標(biāo)志并遞增ah的值。這條指令沒有操作數(shù)。 aas修改al的值為一個有效的未壓縮十進(jìn)制數(shù)據(jù),并將高四位清零。aas必須跟著al中兩個有效未壓縮十進(jìn)制操作數(shù)差。如果需要進(jìn)位將設(shè)置CF標(biāo)志并遞減ah的值。這條指令沒有操作數(shù)。 aam修正兩個有效未壓縮十進(jìn)制數(shù)的積。aam必須跟著兩個十進(jìn)制數(shù)字的積來生成一個有效的十進(jìn)制結(jié)果。數(shù)字的高位在ah中,低位在al 中。這條指令用來調(diào)整ax來生成兩個任何基數(shù)的未壓縮數(shù)字。標(biāo)志版本的這條指令沒有操作數(shù),另一種有一個操作數(shù) - 一個指定創(chuàng)建數(shù)字基數(shù)的立即數(shù)。 aad修改ah保存的分子和ah和ah中兩個有效未壓縮十進(jìn)制操作數(shù)的商,所以計(jì)算的商將為一個未壓縮十進(jìn)制數(shù)據(jù)。ah為高位,al為低位。這條指令調(diào)整al的值,結(jié)果也在al中,而ah內(nèi)容為0.這條指令用來調(diào)整任何基數(shù)的兩個未壓縮數(shù)字。操作數(shù)規(guī)則和aam質(zhì)量相同。 2.1.5 邏輯指令not將指定操作數(shù)求反。它不影響標(biāo)志。操作數(shù)規(guī)則和inc指令相同。 and,or和xor質(zhì)量執(zhí)行標(biāo)準(zhǔn)的邏輯操作。它們更新標(biāo)志SF,ZF和PF。操作數(shù)規(guī)則和add指令相同。 bt,bts,btr和btc指令只能處理一個在內(nèi)存或寄存器中的位。該位位置由操作數(shù)的低位指定。偏移有第二個操作數(shù)指定,它可以為字節(jié)立即數(shù)或 一個通用寄存器。這些指令首先將選擇的位送到標(biāo)志CF。bt指令不會做更多操作,bts設(shè)置選擇位為1,btr將選擇為置為0,btc修改將改位值求反。 第一個操作數(shù)可以為字或雙字。 bt ax,15 ; 測試寄存器中的位 bts word [bx],15 ; 測試并設(shè)置內(nèi)存值中的位 btr ax,cx ; 測試并重置寄存器中的位 btc word [bx],cx ; 測試并求反內(nèi)存值中的位 bsf和bsr質(zhì)量掃描字或雙字第一個為1的位,并將改為索引保存到必須為通用寄存器的目的操作數(shù)。源操作數(shù)可以為通用寄存器或內(nèi)存。當(dāng)整個串為0 時設(shè)置ZF標(biāo)志;否則將置為0。如果沒有找到為1的位,謎底寄存器的值為未定義的。bsf從低位到高位掃描(從位索引0開始)。bsr從高位到低位掃描 (16位時從第15位,32位時從31位開始)。 bsf ax,bx ; 向前掃描寄存器 bsr ax,[si] ; 逆向掃描內(nèi)存值 shl左移目的操作數(shù)為第二個操作數(shù)指定的位數(shù)。目的操作數(shù)可以為字節(jié),字,或雙字通用寄存器或內(nèi)存。第二個操作數(shù)可以為立即數(shù)或cl寄存器。左移的最后一位將被放到標(biāo)志CF中。sal和shl為相同指令。 shl al,1 ; 左移寄存器一位 shl byte [bx],1 ; 左移內(nèi)存值一位 shl ax,cl ; 左移寄存器為cl中的值 shl word [bx],cl ; 左移內(nèi)存值為cl中的值 shr和sar右移目的操作數(shù)為第二個參數(shù)指定的位數(shù)。操作數(shù)規(guī)則和shl指令相同。shr右移的最后一位將放到標(biāo)志CF中。sar保留操作數(shù)符號位,如果操作數(shù)為正數(shù)用0左移,否則用1左移。 shld左移目的操作數(shù)(第二個操作數(shù))為第三個操作數(shù)指定的位數(shù),lefto do。目的操作數(shù)為字或雙字通用寄存器或內(nèi)存,源操作數(shù)必須為通用寄存器,第三個操作數(shù)可以為立即數(shù)或cl寄存器。 shld ax,bx,1 ; 左移寄存器1位 shld [di],bx,1 ; 左移內(nèi)存值一位 shld ax,bx,cl ; 左移寄存器為cl中的位數(shù) shld [di],bx,cl ; 左移內(nèi)存值為cl中的位數(shù) shrd右移目的操作數(shù),lefto to do。不修改源操作數(shù)。操作數(shù)規(guī)則和shld指令相同。 rol和rcl左轉(zhuǎn)字節(jié),字或雙字目的操作數(shù)為第二個操作數(shù)指定的位數(shù)。對于每次轉(zhuǎn)動,左轉(zhuǎn)出來的位數(shù)將成為這個值新的低位。rcl指令還將把高位放到標(biāo)志CF中。操作數(shù)規(guī)則和shl指令相同。 ror和rcr右轉(zhuǎn)字節(jié),字或雙字目的操作數(shù)為第二個操作數(shù)指定的位數(shù)。對于每次轉(zhuǎn)東,右轉(zhuǎn)出來的位數(shù)將成為這個值新的高位。rcr指令還將把低位放到標(biāo)志CF中。操作數(shù)規(guī)則和shl質(zhì)量相同。 test執(zhí)行和and指令相同的操作,但它不會修改目的操作數(shù)的值,只更新標(biāo)志。操作數(shù)規(guī)則和and指令相同。 bswap翻轉(zhuǎn)32位通用寄存器:0到7位翻轉(zhuǎn)為23到31位,8到15位翻轉(zhuǎn)為16位到23位。這條指令用來轉(zhuǎn)換little-endian值為big-endian格式,反之亦然。 bswap edx ; 翻轉(zhuǎn)寄存器值 2.1.6 控制轉(zhuǎn)移指令jmp無條件轉(zhuǎn)移控制到目的位置。目的地址可以直接在指令中指定或間接通過寄存器或內(nèi)存,允許的地址大小取決于跳轉(zhuǎn)類型為near或far(通過在 操作數(shù)前指定near或far操作數(shù)來指定)以及指令是否為16位或32位。對于16位指令near跳轉(zhuǎn)操作數(shù)為16位,32位指令為32位。16位 far跳轉(zhuǎn)操作數(shù)大小為32位,32位指令為64位。一個直接jmp指令 包括作為指令一部分的目的地址(可以包含short,near或far操作符),指定地址的操作數(shù)對于near或短跳轉(zhuǎn)為數(shù)值表達(dá)式,對于far跳轉(zhuǎn)為兩 個用冒號分隔的數(shù)值表達(dá)式。第一個指定段選擇子,第二個為段中偏移。pword操作符可強(qiáng)制為32位far調(diào)用,dword強(qiáng)制為16位far調(diào)用。間接 jmp指令間接從寄存器或指針變量中獲取目的地址,操作數(shù)應(yīng)為通用寄存器或內(nèi)存。細(xì)節(jié)見1.2.5節(jié)。 jmp 100h ; 直接near跳轉(zhuǎn) jmp 0FFFFh:0 ; 直接far跳轉(zhuǎn) jmp ax ; 間接near跳轉(zhuǎn) jmp pword [ebx]; 間接far跳轉(zhuǎn) call轉(zhuǎn)移控制到過程,保存call后指令地址到堆棧,稍后將被ret(返回)指令使用。操作數(shù)規(guī)則和jmp指令相同,但call沒有直接種類因此它不是最優(yōu)的。 ret,retn和retf指令結(jié)束過程執(zhí)行將轉(zhuǎn)移控制給堆棧中call指令壓入的地址。ret等價于retn,retn從near調(diào)用過程返回, 而retf從far調(diào)用過程返回。這些指令默認(rèn)地址大小和當(dāng)前代碼設(shè)置適合,但也可以使用retw,retnw和retfw助記符來強(qiáng)制大小為16位,使 用retd,retnd和retfd助記符強(qiáng)制大小為32位。這些指令可可選的指定一個立即數(shù)操作數(shù),用它和堆棧指針相加,它的作用是在執(zhí)行call指令 之前移除調(diào)用程序壓入堆棧的參數(shù)。 iret返回控制到中斷過程。它不同于ret的地方是它還將彈出堆棧中的標(biāo)志到標(biāo)志寄存器。這個標(biāo)志是由中斷機(jī)制保存的。它默認(rèn)返回地址為當(dāng)前代碼設(shè)置,但也可以使用iretw或iretd助記符來強(qiáng)制使用16位或32位。 條件轉(zhuǎn)移指令根據(jù)指令執(zhí)行時CPU標(biāo)志狀態(tài)來決定是否轉(zhuǎn)移控制。條件跳轉(zhuǎn)助記符可以通過j助記符后面跟著表格2.1列出的條件助記符來得到,例如 jc指令在CF設(shè)置時轉(zhuǎn)移控制。條件跳轉(zhuǎn)可以為short或near,僅能直接跳轉(zhuǎn),并且能優(yōu)化(見1.2.5),操作數(shù)為指定目的地址的立即數(shù)。 loop指令為使用cx(或ecx)中指定軟循環(huán)次數(shù)的條件跳轉(zhuǎn)。所有l(wèi)oop指令自動遞減cx(或ecx),并且在cx(或ecx)為0時結(jié)束循 環(huán)。使用cx還是ecx取決于當(dāng)前代碼設(shè)置為16位還是32為,但也可以使用loopw助記符強(qiáng)制使用cx或使用loopd助記符強(qiáng)制使用ecx。 loope和loopz是相同指令,用作標(biāo)準(zhǔn)loop,但它也在ZF為1時結(jié)束循環(huán)。loopew和loopzw強(qiáng)制使用cx寄存器,looped和 loopzd強(qiáng)制使用ecx寄存器。loopne和loopnz是相同指令,用作標(biāo)準(zhǔn)loop,但它也在ZF為0時結(jié)束循環(huán)。loopnew和 loopnzw助記符強(qiáng)制使用cx寄存器,loopned和loopnzd強(qiáng)制使用ecx寄存器。每一個loop指令都需要一個立即數(shù)值來指定目的地址, 它只能為短調(diào)整(跟在loop指令前128字節(jié)和指令后127字節(jié)范圍)。 jcxz在cx值為0時跳到指定標(biāo)號,jecxz類似,但在ecx為0時跳到指定標(biāo)號。操作數(shù)規(guī)則和loop指令類似。 int激活操作數(shù)指定的中斷服務(wù)過程,中斷號范圍在0到255之間。中斷服務(wù)過程以iret指令結(jié)束,返回控制給int后的指令。int3助記符為短格式的調(diào)用中斷3的指令。into指令當(dāng)OF為1的話調(diào)用中斷。 bound檢查指定寄存器中的符號值是否在指定范圍內(nèi)。如果不在這個范圍將產(chǎn)生中斷5。它需要兩個參數(shù),第一個操作數(shù)為要測試的寄存器,第二個操作數(shù)為范圍。操作數(shù)大小為word或dword。 bound ax,[bx] ; 檢查word數(shù)據(jù)邊界 boudn eax,[esi]; 檢查dword數(shù)據(jù)邊界
2.1.7 I/O 指令in從輸入端口傳輸字節(jié),字或雙字到al,ax,或eax。I/O端口可以用與指令一起編碼的字節(jié)立即數(shù)直接尋址,或間接使用dx寄存器。目的操作數(shù)為al,ax或eax寄存器。源操作數(shù)應(yīng)當(dāng)為0到255之間的立即數(shù),或dx寄存器。 in al,20h ; 從端口20h輸入字節(jié) in ax,dx ; 從dx尋址的端口輸入字 out傳送字節(jié),字,或者雙字到al,ax,或eax指定的輸出端口。程序可以使用與in指令相同的方法指定端口號。目的操作數(shù)應(yīng)當(dāng)為0到255之間的立即數(shù),或dx寄存器。源操作數(shù)應(yīng)為al,ax或eax寄存器。 out 20h,ax ; 輸出字道端口20h out dx,al ; 輸出字節(jié)到dx尋址的端口 2.1.8 字符串操作指令字符串操作針對字符串的一個元素。字符串元素可以為字節(jié),字或雙字。字符串元素用si和di(或esi和edi)尋址。每次字符串操作后si和或 di(或esi和或edi)自動更新指向字符串中后一個元素。如果DF(方向標(biāo)志位)為0,將遞增索引寄存器,否則將遞減。取決于字符串元素的大小在遞增 或遞減大小為1,2或4。每一個字符串操作指令都有不使用任何操作數(shù)的簡短格式,在16位下使用si或和di,在32位下使用esi或和edi。si和 esi默認(rèn)從ds段中定位數(shù)據(jù),di和edi默認(rèn)從es段中定位數(shù)據(jù)。當(dāng)字符串操作助記符后跟著指定字符串元素大小的字母時將使用短格式,“b”為字節(jié)元 素,“w”為字元素,“d”為雙字元素。字符串操作完整格式需要指定尺寸操作符和內(nèi)存地址的操作數(shù),操作數(shù)可以為跟有任何段前綴的si或esi,di或 edi通常和es段前綴使用。 movs傳送si(或esi)指向的字符串元素到di(或edi)指向的地址。操作數(shù)尺寸可以為byte,word或dword。目的操作數(shù)應(yīng)當(dāng)為di或edi尋址的內(nèi)存,源操作數(shù)應(yīng)當(dāng)為跟著任何段前綴si或esi尋址的內(nèi)存。 movs byte [di],[si] ; 傳送字節(jié) movs word [es:di],[ss:si] ; 傳送字 movsd ; 傳送雙字 cmps用目的字符串元素減去源字符串元素并更新標(biāo)志AF,SF,PF,CF和OF,但它不會修改任何比較元素。如果字符串元素相當(dāng),ZF設(shè)置為1,否則為0。第一個操作數(shù)為帶有任何段前綴的si或esi定位的源字符串元素,第二個操作數(shù)為di或edi定位的目的字符串。 cmpsb ; 比較字節(jié) cmps word [ds:si],[es:di] ; 比較字 cmps dword [fs:esi],[edi] ; 比較雙字 scas用al,ax,或eax(取決于字符串元素的尺寸)減去目的字符串元素并更新標(biāo)志AF,SF,ZF,PF,CF和OF。如果值相等,ZF將設(shè)置為1,否則為0.操作數(shù)因?yàn)閐i或edi定位的目的字符串元素。 scas byte [es:di] ; scan 字節(jié) scasw ; scan 字 scas dword [es:edi] ; scan 雙字 lods載入字符串元素到al,ax,或eax。操作數(shù)因?yàn)閹в腥魏味吻熬Y的si或esi尋址的字符串元素。 lods byte [ds:si] ; load 字節(jié) lods word [cs:si] ; load 字 lodsd ; load 雙字 stos將al,ax,或eax的值放到目的字符串元素。字符串規(guī)則和scas指令相同。 ins從dx尋址的輸入端口傳送一個字節(jié),字或者雙字到目的字符串元素。目的操作數(shù)應(yīng)當(dāng)為di或edi尋址的內(nèi)存,源操作數(shù)應(yīng)當(dāng)為dx寄存器。 insb ; input 字節(jié) ins word [es:di],dx ; input 字 ins dword [edi],dx ; input 雙字 outs傳送源字符串元素到dx寄存器尋址的輸出端口。目的操作數(shù)應(yīng)當(dāng)dx寄存器,源操作數(shù)應(yīng)當(dāng)為帶有可帶有任何段前綴的si或esi尋址的內(nèi)存。 outs dx,byte [si] ; output 字節(jié) outsw ; output 字 outs dx,dword [gs:esi] ; output 雙字 重復(fù)前綴rep,repe/repz,和repne/repnz指定重復(fù)字符串操作。當(dāng)一個字符串操作指令包含重復(fù)前綴時,操作將重復(fù)執(zhí)行,每一次 將使用不同的字符串元素。當(dāng)前綴指定的一個條件滿足時結(jié)束重復(fù)。每次操作后所有3個前綴自動遞減cx或ecx寄存器(取決于是否字符串操作指令使用16位 或32位尋址),并且重復(fù)指定的操作指導(dǎo)cx或ecx為0。repe/repz和repne/repnz僅和scas和cmps指令使用(下面講述的)。 當(dāng)使用這些前綴時,取決于ZF標(biāo)志重復(fù)后面的指令,此外,當(dāng)ZF為0時repe和repz結(jié)束執(zhí)行,當(dāng)ZF為1時,repne和repnz結(jié)束執(zhí)行。 rep movsd ; 傳送多個雙字 repe cmpsb ; 比較字節(jié)直到不相等 2.1.9 標(biāo)志控制指令標(biāo)志控制指令用來直接修改標(biāo)志寄存器中的狀態(tài)位。這節(jié)講述的所有指令都沒有操作數(shù)。 stc設(shè)置進(jìn)位標(biāo)志CF為1,clc清零CF,cmc逆反CF的值。std設(shè)置方向標(biāo)志DF為1,cld清零DF,sti設(shè)置中斷標(biāo)志IF為1以允許中的,cli清零IF以禁止中斷。 lahf拷貝SF,ZF,AF,PF,和CF到ah寄存器的位7,6,4,2,和0。其余位將不受影響。 標(biāo)志位保持不變。 sahf將ah的位7,6,2,和0傳送到SF,ZF,AF,PF,和CF。 pushf將esp值遞減2或4,壓入低16位或32位的符號寄存器到堆棧,壓入數(shù)據(jù)大小取決于當(dāng)前代碼設(shè)置。pushfw強(qiáng)制壓入16位,pushfd強(qiáng)制壓入32位。 popf從棧頂彈出16位或32位數(shù)據(jù)到符號寄存器,然后遞減esp值為2或4,遞減大小取決于當(dāng)前代碼設(shè)置。popfw強(qiáng)制彈出16位,popfd強(qiáng)制彈出32位。 2.1.10 條件操作指令這些指令有set助記符,條件助記符(見表2.1)組成,如果條件為true設(shè)置一個字節(jié)為1否則為置為0。操作數(shù)必須為8位的通用寄存器或內(nèi)存中字節(jié)。 setne al ; 如果ZF為0設(shè)置al seto byte [bx] ; 如果溢出設(shè)置byte salc指令當(dāng)CF為0時設(shè)置al的所有位為1,否則都置為0.這條指令沒有參數(shù)。 cmov助記符后面跟著條件助記符組成的指令,僅當(dāng)條件滿足時傳送通用寄存器中的word或dword到通用寄存器。目的操作數(shù)必須為通用寄存器,源操作數(shù)可以為通用寄存器或內(nèi)存。 cmove ax,bx ; 當(dāng)ZF為1時傳送 cmovnc eax,[ebx] ; 當(dāng)CF為0時傳送 cmpxchg比較al,ax或eax和目的操作數(shù)。如果兩個值相等,源操作數(shù)載入到目的操作數(shù),否則目的操作數(shù)載入到al,ax或eax寄存器。目的操作數(shù)可以為通用寄存器或內(nèi)存,源操作數(shù)必須為通用寄存器。 cmpxchg dl,bl ; 和寄存器比較并交換 cmpxchg [bx],dx ; 和內(nèi)存比較并交換 cmpxchg8b比較edx和eax組成的64位值和目的操作數(shù)比較。如果值相等,ecx和ebx中64位值將保存到目的操作數(shù)。否則目的操作數(shù)值保存到edx和eax寄存器。目的寄存器必須為內(nèi)存中的qword。 cmpxchg8b [bx] ; 比較并交換8字節(jié) 2.1.11 其他指令nop指令占用一個字節(jié)但除了指令指針外沒有任何作用。這條指令沒有操作數(shù),不會執(zhí)行任何操作。 ud2指令生成一個無效的指令異常。這條指令用作軟件測試來顯式字生成一個無效指令。這條指令沒有操作數(shù)。 xlat替換al寄存器字節(jié)為bx或ebx尋址的轉(zhuǎn)換表中al索引的字節(jié)。操作數(shù)必須為可帶有任何段前綴的bx或ebx尋址的內(nèi)存中一個字節(jié)。這條指令有一個沒有任何操作數(shù)的短格式xlatb,它使用ds段寄存器中bx或ebx(取決于當(dāng)前代碼設(shè)置)中的地址。 lds轉(zhuǎn)移源操作數(shù)中的指針變量到ds和目的寄存器。源操作數(shù)必須為內(nèi)存操作數(shù),目的寄存器必須為通用寄存器。ds寄存器接受段選擇子,目的寄存器 接受指針偏移部分。les,lfs,lgs和lss操作和lds類似,只是它們分別使用es,fs,gs和ss寄存器,而不是ds寄存器。 lds bx,[si] ; 載入指針到ds:bx lea傳輸源操作數(shù)偏移(而不是值)到目的寄存器。源操作數(shù)必須為內(nèi)存操作數(shù),目的寄存器必須為同一寄存器。 lea dx,[bx+si+1] ; 載入有效地址到dx cpuid返回處理器標(biāo)識和特性信息到eax,ebx,ecx和edx寄存器。指令執(zhí)行前eax寄存器為參數(shù)。該指令沒有操作數(shù)。 pause指令延遲指定時間執(zhí)行下一條指令。它可用來提高死等效率。這條指令沒有操作數(shù)。 enter創(chuàng)建堆??蚣?,可用作實(shí)現(xiàn)塊結(jié)構(gòu)高級語言的范圍規(guī)則。leave指令在過程結(jié)束后和過程開頭的enter一起用來簡化堆棧管理,并用作嵌 套過程中控制訪問變量。enter指令有兩個參數(shù)。第一個指定堆棧中要分配的動態(tài)存儲字節(jié)大小。第二個參數(shù)為相應(yīng)嵌套層數(shù),范圍為0到31。指定層數(shù)決定 了多少堆??蚣苤羔槒那懊嬉粋€框架中拷貝新的堆??蚣堋6褩?蚣芡ǔ=凶鲲@示。顯示的第一個word(當(dāng)代碼為32位時為dword)為最后的堆??蚣堋? 這個指針允許leave指令通過廢棄上一個堆棧幀來逆向前面的enter指令動作。當(dāng)enter為過程創(chuàng)建一個新的顯示后,通過遞減esp為指定字節(jié)來分 配需要的動態(tài)存儲空間。允許過程尋址顯示,enter保留bp(后ebp)指向新堆??蚣?。如果嵌套層數(shù)為0,enter壓入bp(或ebp),拷貝sp 到bp(或esp到ebp),然后esp遞減第一個操作數(shù)大小。對于嵌套層數(shù)大于0的,處理器在調(diào)整堆棧指針前壓入額外的框架指針。 enter 2048,0 2.1.12 系統(tǒng)指令lmsw載入操作數(shù)到機(jī)器狀態(tài)字(CR0的0到15位),而smsw保存機(jī)器狀態(tài)字到目的操作數(shù)。這兩條指令操作數(shù)可以為16位通用寄存器,對于smsw還可以為32位通用寄存器。 lmsw ax ; 從寄存器載入機(jī)器狀態(tài)字 smsw [bx] ; 載入機(jī)器狀態(tài)字到內(nèi)存 lgdt和lidt指令分別用來載入操作數(shù)中的值到全局描述表寄存器和中斷描述表寄存器。sgdt和sidt分別用來保存全局描述表或中斷描述表寄存器到目的操作數(shù)。操作數(shù)必須為內(nèi)存中的6個字節(jié)。 lgdt [ebx] ; 載入全局描述表 lldt載入操作數(shù)到局部描述表寄存器的選擇子,sldt保存局部描述表寄存器段選擇子到操作數(shù)。ltr載入操作數(shù)到任務(wù)寄存器段選擇子,str保存任務(wù)寄存器選擇子到操作數(shù)。操作數(shù)規(guī)則和lmsw,smsw指令相同。 lar載入源操作數(shù)指定的選擇子對應(yīng)的段描述符訪問權(quán)限到目的操作數(shù),并設(shè)置ZF標(biāo)志。目的操作數(shù)可以為16位或32為通用寄存器。源操作數(shù)必須為16位通用寄存器或內(nèi)存。 lar ax,[bx] ; 載入訪問權(quán)限到word lar eax,dx ; 載入訪問權(quán)限到dword lsl從源操作數(shù)選擇子指定的段描述符的段限制到目的操作數(shù)并設(shè)置ZF標(biāo)志。操作數(shù)規(guī)則和lar指令相同。 verr和verw檢查操作數(shù)指定代碼或數(shù)據(jù)段是否能以當(dāng)前特權(quán)級上讀或?qū)?。操作?shù)必須為word,可以為通用寄存器或內(nèi)存。如果可用段并且可讀(對于verr)或可寫(對于verw),將設(shè)置ZF為1,否者ZF置為0。操作數(shù)規(guī)則和lldt指令相同。 arpl比較兩個段選擇子的RPL(請求特權(quán)級)。第一個操作數(shù)包含一個段選擇子,第二個包含另一個。如果目的操作數(shù)RTL小于源操作數(shù)的RPL,ZF置為1,否則置為0,這條指令不影響目的操作數(shù)。目的操作數(shù)可以為16位通用寄存器或內(nèi)存,源操作數(shù)必須為通用寄存器。 arpl bx,ax ; 調(diào)整寄存器選擇子RPL arpl [bx],ax ; 調(diào)整內(nèi)存選擇子RPL clts清零CR0寄存器的任務(wù)切換TS位。這條指令沒有操作數(shù)。 lock前綴導(dǎo)致處理器在執(zhí)行該指令期間斷言總線鎖定信號,總線鎖定信號保證處理器在信號斷言期間獨(dú)占使用任何共享內(nèi)存。lock前綴只能用在以下 指令,并且目的操作數(shù)為內(nèi) 存:add,adc,and,btc,btr,bts,cmpxchg,cmpxchg8b,dec,inc,neg,not,or,sbb,sub,xor,xadd 和xchg。如果lock前綴和上面其中一指令使用并且源操作數(shù)為內(nèi)存,可能會產(chǎn)生未定義指令異常。一個未定義指令異常也可能在lock和不在上面列出的 指令一起使用的時候產(chǎn)生。xchg指令常用來斷言總線鎖定信號無論是否使用lock前綴。 invlpg無效(寫)操作數(shù)指定的轉(zhuǎn)換后援緩沖項(xiàng)TLB。處理器定位這些地址包含的頁并為這些頁回寫TLB項(xiàng)。 rdmsr載入64位MSR(model specific register)ecx中的地址到edx和eax。wrmsr寫edx和eax到ecx寄存器指定的64位MSR。rdtsc從64位MSR載入當(dāng)前處 理器時間戳到edx和eax寄存器。處理器每一時鐘周期遞增MSR時間戳,每次處理器重置時重置時間戳為0。rdpmc載入edx寄存器指定的40位性能 監(jiān)視計(jì)數(shù)器到edx和eax。這些指令沒有操作數(shù)。 wbinvd回寫處理器內(nèi)部緩沖中所有修改的緩沖行到主內(nèi)存,并且無效內(nèi)部緩沖。然后創(chuàng)建一個特殊函數(shù)總線周期來指導(dǎo)外部緩沖也回寫外部修改數(shù)據(jù)以及另一個時鐘周期來標(biāo)識外部緩沖無效。這條指令沒有操作數(shù)。 rsm從系統(tǒng)管理模式返回到當(dāng)處理器接受SMM中斷時所處的模式。這條指令沒有操作數(shù)。 sysenter執(zhí)行到ring 0系統(tǒng)過程的快速調(diào)用,sysexit執(zhí)行到ring 3的快速返回。這些指令是否可用有MSR相關(guān)位標(biāo)識。這些指令沒有操作數(shù)。 2.1.13 FPU 指令浮點(diǎn)單元FPU指令操作三種格式的浮點(diǎn)數(shù)據(jù):單精度(32位),雙精度(64位)和擴(kuò)展雙精度(80位)。FPU寄存器構(gòu)成一個堆棧,并且它們都是 擴(kuò)展雙精度的。當(dāng)從堆棧中壓入或彈出一些值時,F(xiàn)PU寄存器移動,所以st0一直為FPU堆棧棧頂?shù)闹?,st1為棧頂下的第一個值。st0和st是同義 詞。 fld壓入浮點(diǎn)數(shù)據(jù)到FPU寄存器堆棧。操作數(shù)可以為32位,64位或80位內(nèi)存地址或FPU寄存器,其值將稍后載入到FPU寄存器堆棧棧頂(也就是st0寄存器),并且自動轉(zhuǎn)換為擴(kuò)展雙精度格式。 fld dword [bx] ; 從內(nèi)存載入單精度浮值。 fld st2 ; 壓入st2的值到寄存器堆棧 fld2,fldz,fldl2t,fldl2e,fldpi,fldlg2和fldln2載入常用的常量到FPU寄存器堆棧。載入的常量分別為:+1.0,+0.0,log2|10,log2|e,pi,log10|2和ln2。這些指令沒有操作數(shù)。 fild轉(zhuǎn)換一個源操作數(shù)整數(shù)為擴(kuò)展雙精度浮點(diǎn)格式,并將結(jié)果壓入FPI寄存器堆棧。源操作數(shù)可以為16位,32位,或64位內(nèi)存地址。 fild qword [bx] ; 從內(nèi)存載入64位整數(shù) fst拷貝st0寄存器的值到目的操作數(shù),目的操作數(shù)可以為32位或64位內(nèi)存地址或另一個FPU寄存器。fstp執(zhí)行和fst相同的操作,只是它還將彈出寄存器堆棧。fstp執(zhí)行和fst相同的操作,只是它還將壓入一個80位內(nèi)存中的值。 fst st3 ; 拷貝st0值到st3寄存器 fstp tword [bx] ; 存儲內(nèi)存中值并彈出堆棧 fist轉(zhuǎn)換st0值為一整數(shù),并保存結(jié)果到目的操作數(shù)。操作數(shù)可以為61位或32位內(nèi)存地址。fistp執(zhí)行相同操作,但很將彈出寄存器堆棧,并能存儲值到64位內(nèi)存,操作數(shù)規(guī)則和fild指令相同。 fbld轉(zhuǎn)換壓縮BCD整數(shù)為擴(kuò)展雙精度浮點(diǎn)格式并壓入值到FPU堆棧。fbstp轉(zhuǎn)換st0中的值為18個數(shù)字壓縮BCD整數(shù),保存結(jié)果到目的操作數(shù)并彈出寄存器堆棧。操作數(shù)應(yīng)為80位內(nèi)存地址。 fadd計(jì)算目的和源操作數(shù)的和并保存結(jié)果到目的操作數(shù)。目的操作數(shù)一直為FPU寄存器,如果源操作數(shù)為內(nèi)存地址,目的操作數(shù)為st0寄存器并且只指定源操作數(shù)。內(nèi)存操作數(shù)可以為32位或64位值。 fadd qword [bx] ; 計(jì)算擴(kuò)展雙精度和st0的和 fadd st2,st0 ; 計(jì)算st0和st2的和 faddp計(jì)算目的和源操作數(shù)的和,并保持結(jié)果到目的位置,然后彈出堆棧。目的操作數(shù)必須為FPU寄存器,源操作數(shù)必須為st0。當(dāng)沒有指定操作數(shù)時,將使用st1作為目的操作數(shù)。 faddp ; 計(jì)算st0和st1的和并彈出堆棧 faddp st2,st0 ; 計(jì)算st0和st2的和并彈出堆棧 fiadd指令轉(zhuǎn)換源操作數(shù)整數(shù)為擴(kuò)展雙精度浮點(diǎn)數(shù),并和目的操作數(shù)相加。操作數(shù)必須為16位或32位內(nèi)存地址。 fiadd word[bx] ; word整數(shù)和st0相加 fsub,fsubr,fmul,fdiv,fdivr指令和fadd類似,操作數(shù)規(guī)則和fadd相同。fsub計(jì)算目的操作數(shù)和源操作數(shù)的 差,fsubr計(jì)算源操作數(shù)和目的操作數(shù)的差,fmul將目的和源操作數(shù)相乘。fdivr計(jì)算目的操作數(shù)和源操作數(shù)的差,fdivr計(jì)算源操作數(shù)和目的操 作數(shù)的差。fsubp,fsubrp,fmulp,fdivp,fidivr在轉(zhuǎn)換源操作數(shù)整數(shù)為浮點(diǎn)數(shù)據(jù)后執(zhí)行這些操作,它們操作數(shù)的規(guī)則和fiadd 指令相同。 fsqrt計(jì)算st0寄存器中值的開方。fsin計(jì)算值的sin,fabs清除符號位來得到絕對值,frndint根據(jù)當(dāng)前四舍五入模式來得到最接 近的整數(shù)值。f2xm1計(jì)算2的以st0為冪的指數(shù),并減去1.0,st0的值的范圍必須在-1.0和+1.0之間。所有這些指令保存結(jié)果到st0并且沒 有操作數(shù)。 fsincos計(jì)算st0值的sin和cos,保存sin結(jié)果到st0,壓入cos值到FPU寄存器堆棧。fptan計(jì)算st0的tag值,保存結(jié) 果到st0,并壓入值1.0堆棧。fpatan計(jì)算st1的arctag,并和st0相除,保存結(jié)果到st1并彈出寄存器堆棧。fyl2x計(jì)算st0的二 進(jìn)制算術(shù)結(jié)果,乘以st1值,保存結(jié)果到st1,然后彈出FPU寄存器堆棧。fyl2xp1執(zhí)行相同操作,但它在計(jì)算對數(shù)前和1.0相加,保存結(jié)果到 st0。fprem計(jì)算st0和st1相除的余數(shù)到st1,結(jié)果到st0。fprem1執(zhí)行和fprem相同的操作,但它計(jì)算IEEE標(biāo)志754指定的余 數(shù)。fscale截去st1的值并和st0值相加。fxtract分隔st0值為指數(shù)和有效數(shù)字,保存指數(shù)到st0,壓入有效數(shù)字到寄存器堆棧。fnop 不執(zhí)行任何操作。這些指令沒有操作數(shù)。 fxch交換st0和另一個FPU寄存器的內(nèi)容。這個操作數(shù)必須為FPU寄存器,不用指定操作數(shù),st0和st1內(nèi)容將被交換。 fcom和fcomp比較st0和源操作數(shù),并格局結(jié)構(gòu)設(shè)置FPU狀態(tài)字標(biāo)志。fcomp執(zhí)行操作后還將彈出寄存器堆棧。操作數(shù)可以為內(nèi)存中單精度或雙精度浮點(diǎn)或FPU寄存器。當(dāng)沒有指定源操作數(shù)時將使用st1. ficom word [bx] ; 16位整數(shù)和st0比較 fcomi,fcomip,fucomi,fucomip用st0和另一個FPU寄存器比較并根據(jù)結(jié)果設(shè)置標(biāo)志ZF,PF和CF。fcomip和 fucomip還將在執(zhí)行操作后彈出寄存器堆棧。fcmov助記符后面跟著表2.2列出的FPU條件助記符組成的指令如果給定測試條件為true時傳送指 定FPU寄存器到st0寄存器。這些指令有兩種不同語法,一種是跟著指定源FPU寄存器的單一操作數(shù),另一種帶有兩個操作數(shù),此時目的操作數(shù)為st0,第 二個操作數(shù)為源FPU寄存器。 fcomi st2 ; 比較st0和st2并設(shè)置標(biāo)志 fcmovb st0,st2 ; 如果小于傳送st2到st0
ftst比較st0和0.0并根據(jù)結(jié)果設(shè)置FPU狀態(tài)字標(biāo)志。fxam檢查st0內(nèi)容并設(shè)置FPU狀態(tài)字來標(biāo)識該寄存器值類型。這些指令沒有操作數(shù)。 fstsw和fnstsw保存當(dāng)前FPU狀態(tài)字到目的位置。目的操作數(shù)可以為16位內(nèi)容或ax寄存器。fstsw在保持狀態(tài)字前檢查未知的沒有屏蔽的FPU異常,而fnstsw不這么做。 fstcw和fnstcw保存當(dāng)前FPU狀態(tài)字到指定的內(nèi)存中目的地址。fstcw在保持狀態(tài)字前檢查未知沒有屏蔽的FPU異常,而fnstcw不這樣。fldcw載入操作數(shù)到FPU控制字。操作數(shù)必須為16位內(nèi)存地址。 fstenv和fnstenv保存當(dāng)前FPU操作環(huán)境到目的操作數(shù)指定的內(nèi)存地址,然后屏蔽所有FPU異常。fstenv在處理前檢查待處理的未屏 蔽的FPU異常,fnstenv將不檢查。flden從內(nèi)存中載入完整的操作環(huán)境到FPU。fsave和fnsave保存當(dāng)前FPU狀態(tài)(操作環(huán)境和寄存 器堆棧)到內(nèi)存中定制的目的地址并重新初始化FPU。fsave在處理前檢查待處理的非屏蔽FPU異常,fnsave不檢查。frstor從指定內(nèi)存位置 載入FPU狀態(tài)。所有這些指令都需要一個內(nèi)存位置操作數(shù)。 finit和fninit設(shè)置FPU操作環(huán)境到默認(rèn)狀態(tài)。finit在處理前檢查待處理非屏蔽FPU異常,而fninit不檢查。fclex和 fnclex清除FPU狀態(tài)字中FPU異常標(biāo)志。fclex在處理前檢查待處理非屏蔽FPU異常,fnclex不檢查。wait和fwait為相同指令, 將導(dǎo)致處理器檢查待處理的非屏蔽FPU異常并在處理前處理它們。這些指令沒有操作數(shù)。 ffree設(shè)置和指定FPU寄存器相關(guān)的tag為0。操作數(shù)必須為一個FPU寄存器。 fincstp和fdecstp翻轉(zhuǎn)FPU堆棧為1或棧頂指針減1.這些指令沒有操作數(shù)。 2.1.14 MMX 指令MMX指令 操作壓縮整數(shù)或MMX寄存器,MMX寄存器為80位FPU寄存器的低64位。因?yàn)榇薓MX指令不能和FPU指令一起使用。他們可以操作壓縮字節(jié)(八個8位 整數(shù)),壓縮字(四個16位整數(shù))或壓縮雙字(兩個32位整數(shù)),使用壓縮格式允許一次對多個數(shù)據(jù)執(zhí)行操作。 movq從源操作數(shù)拷貝8字節(jié)到目的操作數(shù)。至少一個操作數(shù)必須為MMX寄存器,第二個可以為MMX寄存器或64位內(nèi)存地址。 movq mm0,mm1 ; 寄存器到寄存器移動8字節(jié) movq mm2,[ebx] ; 內(nèi)存到寄存器移動8字節(jié) movd從源操作數(shù)移動雙字到目的操作數(shù)。其中一個操作數(shù)必須為MMX寄存器,第二個可以為通用寄存器或32位內(nèi)存地址。只使用MMX寄存器的低雙字。 所有通用MMX操作有兩個操作數(shù),目的操作數(shù)應(yīng)當(dāng)為MMX寄存器,源操作數(shù)可以為MMX寄存器或64位內(nèi)存地址。對源和目的操作數(shù)執(zhí)行相應(yīng)操作并保 存數(shù)據(jù)單元到目的操作數(shù)。paddb,paddw和paddd計(jì)算壓縮字節(jié),壓縮字,壓縮雙字的和。paddsb,paddsw,psubsb和 psubsw執(zhí)行壓縮字節(jié)或壓縮字的帶符號saturation的和。paddusb,paddusw,psubusb,psubusw類似,但將計(jì)算無 符號saturation。pmulhw和pmullw符號乘壓縮字,保存結(jié)果的高位或低位到目的操作數(shù)。pmaddwd乘壓縮字,加上四個立即雙字對來 生成壓縮雙字結(jié)果。pand,por和pxor執(zhí)行qword邏輯操作。pcmpeqb,pcmpeqw和pcmpeqd比較壓縮字節(jié),壓縮字或壓縮雙字 是否相等。如果某對數(shù)據(jù)元素相等,目的操作數(shù)中相應(yīng)數(shù)據(jù)元素將填充為1,否則填充0.pcmpgtb,pcmpgtw和pcmpgtd執(zhí)行相同操作,但它 們用來檢查是否目的操作數(shù)中數(shù)據(jù)元素大于源操作數(shù)中數(shù)據(jù)元素。packsswb轉(zhuǎn)換帶壓縮符號字為壓縮帶符號字節(jié),使用saturation來處理溢出。 packuswb轉(zhuǎn)換壓縮符號字道壓縮無符號字節(jié)。源操作數(shù)中轉(zhuǎn)換后的數(shù)據(jù)單元存儲到目的操作數(shù)的低部分,目的操作數(shù)中轉(zhuǎn)換后的數(shù)據(jù)單元存儲到高半部分。 punpckhbw,punpckhwd和punpckhdq從源操作數(shù)和目的操作數(shù)高半部分插入數(shù)據(jù)單元并保持結(jié)果到目的操作數(shù)。 punpcklbw,punpcklwd和punpckldq執(zhí)行相同操作,但它們使用源和目的操作數(shù)的低半部分。 paddsb mm0,[esi] ; 計(jì)算壓縮字節(jié)符號saturation和 pcmpeqw mm3,mm7 ; 比較壓縮字是否相當(dāng) psllw,pslld和psllq對壓縮字,壓縮雙字或目的操作數(shù)中的一個qword執(zhí)行邏輯左移,左移位數(shù)由源操作數(shù)指定。 pswlw,psrld和psrlq對壓縮字,壓縮雙字或目的操作數(shù)中的一個qword執(zhí)行邏輯右移。psraw和psrad對壓縮字或雙字執(zhí)行算術(shù)右 移。目的操作數(shù)因?yàn)镸MX寄存器,而源操作數(shù)可以為MMX寄存器,64位內(nèi)存為孩子,或8位立即數(shù)。 psslw mm2,mm4 ; 邏輯左移word psrad mm4,[ebx] ; 算術(shù)右移dword emms是得FPU寄存器可用。如果使用了MMX指令,它必須在使用FPU指令前使用。 2.1.15 SSE 指令SSE擴(kuò)展增加了更多MMX指令,并且能操作壓縮單精度浮點(diǎn)數(shù)。128位壓縮單浮點(diǎn)格式由4個單精度浮點(diǎn)數(shù)組成。128位SSE寄存器設(shè)計(jì)用來操作這種數(shù)據(jù)類型。 movapshemovups傳送源操作數(shù)中一個包含單進(jìn)度值的雙qword操作數(shù)到目的操作數(shù)。至少一個操作數(shù)必須為SSE寄存器,第二個操作數(shù) 可以為SSE寄存器或128位內(nèi)存地址。movaps指令的內(nèi)存操作數(shù)必須對齊在16位字節(jié)邊界,movups指令操作數(shù)不需要對齊。 movups xmm0,[ebx] ; 傳送未對其雙qword movlps在內(nèi)存和SSE寄存器低qword之間移動兩個壓縮單精度數(shù)據(jù)。movhps在內(nèi)存和SSE寄存器高qword之間移動兩個壓縮單精度數(shù)據(jù)。其中一個操作數(shù)必須為SSE寄存器,另一個必須為64位內(nèi)存地址。 movlps xmm0,[ebx] ; 移動內(nèi)存到xmm0低qword movhps [esi],xmm7 ; 移動xmm7高qword到內(nèi)存 movlhps從源寄存器的低qword移動壓縮的兩個浮點(diǎn)數(shù)據(jù)到目的寄存器。movhlps從源寄存器高qword移動兩個壓縮單浮點(diǎn)數(shù)到目的寄存器的低qword。這兩個操作數(shù)都必須為SSE寄存器。 movmskps傳送SSE寄存器中4個單浮點(diǎn)數(shù)據(jù)的最高位到一個通用寄存器的低4位。源操作數(shù)必須為SSE寄存器,目的操作數(shù)必須為通用寄存器。 movss在源和目的操作數(shù)(只傳送低dword)傳送單浮點(diǎn)數(shù)據(jù)。至少一個操作數(shù)必須為SSE寄存器,第二個操作數(shù)可以為SSE寄存器或32位內(nèi)存地址。 movss [edi],xmm3 ; 移動xmm3低dword到內(nèi)存 每一個SSE算術(shù)操作都有兩種。當(dāng)助記符以ps結(jié)尾時,源操作數(shù)可以為128位內(nèi)存地址或SSE寄存器,目的操作數(shù)必須為SSE寄存器,操作壓縮的 四個浮點(diǎn)數(shù)據(jù),對于對應(yīng)數(shù)據(jù)元素對,結(jié)果保存在目的寄存器。當(dāng)助記符以ss結(jié)尾時,源操作數(shù)可以為32位內(nèi)存地址或SSE寄存器,目的操作數(shù)必須為SSE 寄存器,操作于單浮點(diǎn)數(shù)據(jù),此時只適用SSE寄存器的低dword。addps和addss計(jì)算和,mulps和mulss計(jì)算積,divps和 divss計(jì)算目的值和源值的商,rcpps和rcpss計(jì)算源操作數(shù)的近似倒數(shù),sqrtps和sqrtss計(jì)算源操作數(shù)的開放,rsqrtps和 rsqrtss計(jì)算源值的開方的近似倒數(shù),maxps和maxss比較源和目的值并返回大的值,minps和minss計(jì)算源和目的值并返回小的值。 mulss xmm0,[ebx] ; 乘以單浮點(diǎn)數(shù)據(jù) addps xmm3,xmm7 ; 加上壓縮單浮點(diǎn)數(shù)據(jù) andps,andnps,orps和xorps對壓縮單精度數(shù)據(jù)執(zhí)行邏輯操作。源操作數(shù)可以為128位內(nèi)存地址或SSE寄存器,目的操作數(shù)必須為SSE寄存器。 cmpps比較壓縮單精度數(shù)并返回結(jié)果掩碼到目的操作數(shù),目的操作數(shù)只能為SSE寄存器。源操作數(shù)可以為128位誒從地址或SSE寄存器,第三個參 數(shù)必須為表2.3中列出的8個比較條件操作數(shù)立即數(shù)。cmpss對單浮點(diǎn)數(shù)據(jù)執(zhí)行相同的操作,但它只影響目的寄存器的低dowrd,此時源操作數(shù)可以為 32位內(nèi)存地址或SSE寄存器。這兩個指令也包含只有兩個操作數(shù)和條件編碼的助記符。這些助記符有cmp助記符后跟著表2.3列出的助記符,以及ps或 ss構(gòu)成。 cmpps xmm2,xmm4,0 ; 比較壓縮單精度值 cmpltss xmm0,[ebx] ; 比較單精度數(shù)據(jù) comiss和ucomiss比較單精度并設(shè)置標(biāo)志ZF,PF和CF來表示結(jié)果。目的操作數(shù)必須為SSE寄存器,源操作數(shù)可以為32位內(nèi)存地址或SSE寄存器。
shufps從目的操作數(shù)移動任何兩個四單精度數(shù)據(jù)到目的操作數(shù)的低qword,源操作數(shù)中4個值的任何兩個到目的操作數(shù)的高qword。目的操作 數(shù)必須為SSE寄存器,源操作數(shù)可以為128位內(nèi)存地址或SSE寄存器,第三個操作數(shù)必須8位立即數(shù)來指定選擇移動那些數(shù)據(jù)到目的操作數(shù)。位0和1選擇移 動目的操作數(shù)到結(jié)果的低dword,位2和3移動目的操作數(shù)到第二個dword,位4和5移動源操作數(shù)的到結(jié)果的第三個dword,位6和7移動源操作數(shù) 到結(jié)果的高dword。 shufps xmm0,xmm0,10010011b ; 攪亂dword unpckhps執(zhí)行從源和目的操作數(shù)高部分插入的未壓縮數(shù)據(jù),并保存結(jié)果到目的操作數(shù)。源操作數(shù)可以為128位內(nèi)存地址或SSE寄存器。unpcklps執(zhí)行從源和目的操作數(shù)低部分插入的未壓縮數(shù)據(jù),并保持結(jié)果到目的操作數(shù),操作數(shù)規(guī)則相同。 cvtpi2ps轉(zhuǎn)換壓縮的2dword整數(shù)到壓縮的2單浮點(diǎn)數(shù)據(jù),并保存結(jié)果到目的操作數(shù)的低qword,目的操作數(shù)應(yīng)為SSE寄存器。源操作數(shù)可以為64位內(nèi)存地址或MMX寄存器。 cvtpi2ps xmm0,mm0 ; 整合為單精度數(shù) cvtsi2ss轉(zhuǎn)換dword整數(shù)位單精度浮點(diǎn)數(shù)并保存結(jié)果到目的操作數(shù)的低dword,目的操作數(shù)必須為SSE寄存器。源操作數(shù)可以為32位內(nèi)存地址或32位通用寄存器。 ctsi2ss xmm0,eax ; 整合為但精度數(shù) cvtps2pi轉(zhuǎn)換2單精度浮點(diǎn)數(shù)為壓縮2dword整數(shù)并保存結(jié)果到目的操作數(shù),目的操作數(shù)必須為通用寄存器。源操作數(shù)可以為64位內(nèi)存地址或SSE寄存器,只適用SSE寄存器的低qword。cvttps2pi操作結(jié)果類似,除了截去近似為整數(shù),操作數(shù)規(guī)則相同。 cvtps2pi mm0,xmm0 ; 單精度數(shù)到整數(shù) cvtss2si轉(zhuǎn)換2單精度浮點(diǎn)數(shù)為壓縮2dword整數(shù)并保存結(jié)果到目的操作數(shù),目的操作數(shù)必須為32位通用寄存器。源操作數(shù)可以為32位內(nèi)存 地址或SSE寄存器,只適用SSE寄存器的低qword。cvttss2pi操作結(jié)果類似,除了截去近似為整數(shù),操作數(shù)規(guī)則相同。 cvtss2pi eax,xmm0 ; 單精度數(shù)到整數(shù) pextrw拷貝第三個操作數(shù)指定的源操作數(shù)word到目的操作數(shù)。源操作數(shù)必須為MMX寄存器,目的操作數(shù)必須為32位通用寄存器(僅影響低word),第三個操作數(shù)必須為8位立即數(shù)。 pextrw eax,mm0,1 ; 取word到eax pinsrw插入第三個操作數(shù)指定的word到目的操作數(shù)中第三個操作數(shù)指定的位置,第三個操作數(shù)必須為8位立即數(shù)。目的操作數(shù)必須為MMX寄存器,源操作數(shù)可以為16位內(nèi)存地址或32位通用寄存器(只適用寄存器的低word)。 pinsrw mm1,ebx,2 ; 從ebx插入word pavgb和pavgw計(jì)算壓縮字節(jié)或字平均值。pmaxub返回壓縮無符號字節(jié)的最大值,pminub返回壓縮無符號字節(jié)的最小值,pmaxsw 返回壓縮無符號字的最大值,pminsw返回壓縮無符號字的最小值。pmulhuw執(zhí)行無符號壓縮字乘法并保存結(jié)果到目的操作數(shù)的高word。 psadbw計(jì)算壓縮無符號字節(jié)絕對差別,匯總不同點(diǎn),并保存匯總到目的操作數(shù)的低word。所有這些指令操作數(shù)規(guī)則和上一節(jié)講述的MMX操作相同。 pmovmskb創(chuàng)建源操作數(shù)每一個字節(jié)的自高位掩碼,并保存結(jié)果到目的操作數(shù)的低byte。源操作數(shù)必須為MMX寄存器,目的操作數(shù)必須為32位通用寄存器。 pshufw插入word源操作數(shù)到目的操作數(shù)中第三個操作數(shù)指定的位置。目的操作數(shù)必須為MMX寄存器,源操作數(shù)可以為64位內(nèi)存地址或MMX寄存器,第三個操作數(shù)必須8位立即數(shù)用來選擇那些值將移動到目的操作數(shù),和shufps指令第三個操作數(shù)相同方式。 ovntq使用非臨時緩沖提示以最小緩沖損失方式從源操作數(shù)移動qword到內(nèi)存。源操作數(shù)必須為MX寄存器,目的寄存器應(yīng)為64位內(nèi)存地址。 movntps使用非臨時提示從SSE寄存器保存壓縮單精度數(shù)據(jù)到內(nèi)存。源操作數(shù)必須為SSE寄存器,目的操作數(shù)必須為128位內(nèi)存地址。 maskmovq使用非臨時提示方式保存第一個操作數(shù)指定的字節(jié)到64位內(nèi)存地址。兩個操作數(shù)都必須為MMX寄存器,第二個操作數(shù)決定源操作數(shù)中那些字節(jié) 將寫到內(nèi)存中。內(nèi)存地址由DS段中DI(或EDI)寄存器指向。 prefetcht0,prefetcht1,prefetcht2和prefetchnta獲取操作數(shù)指定的字節(jié)所處內(nèi)存數(shù)據(jù)行到指定位置。操作數(shù)應(yīng)為8位內(nèi)存地址。 sfence同步所有在它之前所有創(chuàng)建指令操作。這條指令沒有操作數(shù)。 ldmxcsr載入32位內(nèi)存操作數(shù)到MXCSR寄存器。stmxcsr保存MXCSR內(nèi)容到32位寄存器。 fxsave保存FPU,MXCSR寄存器當(dāng)前狀態(tài),和所有FPU和SSE寄存器內(nèi)容到512字節(jié)目的操作數(shù)指定的內(nèi)存地址。fxrstor重新載 入前面用fxsave指令保存的512字節(jié)內(nèi)存地址。這兩條指令內(nèi)存操作數(shù)必須對齊在16字節(jié)邊界上,它不能聲明任何指定大小操作數(shù)。 2.1.16 SSE2指令SSE2擴(kuò)展用來操作壓縮雙精度浮點(diǎn)數(shù)據(jù),擴(kuò)展MMX指令語法,并且增加了新的指令。 movapd和movupd從源操作數(shù)傳送包含壓縮雙精度數(shù)據(jù)的雙qword操作數(shù)到目的操作數(shù)。這些指令類似movaps和movups,操作數(shù)規(guī)則也相同。 movmskpd傳送SSE寄存器兩個雙精度數(shù)最高位到通用寄存器低兩位。這條指令和movmskps類似并有相同操作數(shù)規(guī)則。 movsd在源和目的操作數(shù)之間傳送雙精度數(shù)(值傳送低qword)。其中至少一個操作數(shù)為SSE寄存器,第二個可以為SSE寄存器或64位內(nèi)存地址。 雙精度值算術(shù)操作 有:addpd,addsd,subpd,subsd,mulpd,mulsd,divpd,divsd,sqrtpd,sqrtsd,maxpd,maxsd,minpd,minsd, 它們和上一節(jié)講述的單浮點(diǎn)算術(shù)操作類似。當(dāng)助記符以pd而不是ps結(jié)尾時,操作針對于壓縮的2雙精度數(shù),但操作數(shù)規(guī)則相同。當(dāng)助記符以sd而不是ss結(jié)尾 時,源操作數(shù)可以為64位內(nèi)存地址或SSE寄存器,目的寄存器必須為SSE寄存器并且操作于雙精度數(shù),此時只適用SSE寄存器的低qword。 andpd,andnpd,orpd和xorpd對壓縮雙精度值執(zhí)行邏輯操作。它們和針對單精度的邏輯操作類似并且有相同的操作數(shù)規(guī)則。 cmppd比較壓縮雙精度數(shù)并返回掩碼結(jié)果到目的操作數(shù)。這條指令和cmpps類似,并且有相同的操作數(shù)規(guī)則。cmpsd對雙精度數(shù)據(jù)執(zhí)行相同操作,但它只影響目的寄存器的低qword。接受兩個操作數(shù)的指令由cmp助記符,表2.3列出的條件助記符和pd或sd組成。 comisd和ucomisd比較雙精度操作數(shù)并設(shè)置標(biāo)志ZF,PF和CF來表示結(jié)果。目的操作數(shù)必須為SSE寄存器,源操作數(shù)可以為128位內(nèi)存地址或SSE寄存器。 shufpd從目的操作數(shù)移動任何兩個雙精度數(shù)到目的操作數(shù)的低qword,源操作數(shù)任何兩個值值到目的寄存器的高qword。這條指令和 shufps類似并且有相同的操作數(shù)規(guī)則。第三個操作數(shù)位0指定將移動到目的操作數(shù)的值,位1選擇將從源操作數(shù)移動的值,其他位為保留的必須為0。 unpckhpd在源和目的操作數(shù)之間執(zhí)行壓縮高qword,unpcklpd在源和目的操作數(shù)之間執(zhí)行未壓縮低qword。它們是unpckhps和unpcklps類似,并且有相同的操作數(shù)規(guī)則。 cvtps2pd轉(zhuǎn)換壓縮2單精度浮點(diǎn)數(shù)據(jù)為兩個壓縮的雙精度浮點(diǎn)數(shù)據(jù),目的操作數(shù)必須為SSE寄存器,源操作數(shù)可以為64位內(nèi)存地址或SSE寄存 器。 cvtpd2ps轉(zhuǎn)換壓縮2擴(kuò)展雙精度浮點(diǎn)數(shù)據(jù)為壓縮2單精度浮點(diǎn)數(shù)據(jù),目的操作數(shù)必須為SSE寄存器,源操作數(shù)可以為128位內(nèi)存地址或SSE寄存器。 cvtss2sd轉(zhuǎn)換單精度浮點(diǎn)數(shù)據(jù)為雙精度浮點(diǎn)數(shù)據(jù),目的操作數(shù)必須為SSE寄存器,源操作數(shù)可以為32位內(nèi)存地址或SSE寄存器。cvtsd2ss轉(zhuǎn) 換擴(kuò)展雙精度數(shù)據(jù)為單精度浮點(diǎn)數(shù)據(jù),目的操作數(shù)必須為SSE寄存器,源操作數(shù)可以為64位內(nèi)存地址或SSE寄存器。 cvtpi2pd轉(zhuǎn)換壓縮2 dword整數(shù)位壓縮雙精度浮點(diǎn)數(shù)據(jù),目的操作數(shù)必須為SSE寄存器,源操作數(shù)可以為64位內(nèi)存地址或MMX寄存器。cvtsi2sd轉(zhuǎn)換一個dword 整數(shù)為雙精度浮點(diǎn)數(shù)據(jù),目的操作數(shù)必須為SSE寄存器,源操作數(shù)可以為32位內(nèi)存地址或32位通用寄存器。cvtpd2pi轉(zhuǎn)換壓縮雙精度浮點(diǎn)數(shù)據(jù)為壓縮 2 dword整數(shù),目的操作數(shù)應(yīng)為MMX寄存器,源操作數(shù)可以為128位內(nèi)存地址或SSE寄存器。cvttpd2pi執(zhí)行類似操作,除了它將源值截?cái)嗟秸? 數(shù),操作數(shù)規(guī)則也一樣。cvtsd2si轉(zhuǎn)換雙精度浮點(diǎn)數(shù)據(jù)為dword整數(shù),目的操作數(shù)應(yīng)為32位通用寄存器,源操作數(shù)可以為64為內(nèi)存地址或SSE寄 存器。cvttsd2si執(zhí)行相同吃哦啊在,除了將源值截為整數(shù),操作數(shù)規(guī)則也一樣。 cvtps2dq和cvttps2dq轉(zhuǎn)換壓縮單精度浮點(diǎn)數(shù)據(jù)為壓縮4 dword整數(shù),保存它們的值到目的操作數(shù)。cvtpd2dq和cvttpd2dq轉(zhuǎn)換壓縮雙精度浮點(diǎn)數(shù)據(jù)為壓縮2 dword整數(shù),保存結(jié)果到目的操作數(shù)的低qword。cvtdq2ps轉(zhuǎn)換壓縮4dword幀數(shù)為壓縮單精度浮點(diǎn)數(shù)據(jù)。cvtdq2pd從源操作數(shù)低 qword轉(zhuǎn)換壓縮2 dword整數(shù)為壓縮雙精度浮點(diǎn)數(shù)據(jù)。所有這些指令目的操作數(shù)必須為SSE寄存器,源操作數(shù)可以為128位內(nèi)存地址或SSE寄存器。 movdqa和movdqu傳送源操作數(shù)中雙qword大小的壓縮整數(shù)為目的操作數(shù)。至少其中一個操作數(shù)必須為SSE寄存器,第二個可以為SSE寄存器或128位內(nèi)存地址。movdqa指令內(nèi)存操作數(shù)必須16字節(jié)對齊,movdqu指令操作數(shù)不需要對齊。 movq2dq移動MMX源寄存器內(nèi)容到目的SSE寄存器低qword。movdq2q傳送源SSE寄存器低qword到目的MMX寄存器。 movq2dq xmm0,mm1 ; MMX寄存器傳送到SSE寄存器 movdq2q mm0,xmm1 ; SSE寄存器傳送到MMX寄存器 所有MMX指令操作的64位壓縮整數(shù)(用p開頭的助記符)擴(kuò)展能操作SSE寄存器中128位壓縮整數(shù)。left to do。pshufw指令另外,它不需要擴(kuò)展語法,但有兩種新的變種:pshufhw和pshuflw,他們只允許擴(kuò)展語法,并且分別針對操作數(shù)高或低 qword執(zhí)行和pshufw相同操作。此外pshufd為新增指令,用來執(zhí)行和pshufw相同的操作,但它操作dword而不是word,它只允許擴(kuò) 展語法。 psubb xmm0,[esi] ; 減16壓縮字節(jié) pextrw eax,xmm0,7 ; 提取最高word到eax paddq執(zhí)行兩個壓縮qword的和,psubq執(zhí)行兩個壓縮qword的差,puludq執(zhí)行無符號乘法每一個對應(yīng)qword的低dword,并返回結(jié)果到壓縮qword。這些指令和2.1.14講述的通用MMX操作有相同規(guī)則。 pslldq和psrldq執(zhí)行邏輯左或右移雙dqword目的操作數(shù),移動位數(shù)由源操作數(shù)指定。目的操作數(shù)必須為SSE寄存器,源操作數(shù)應(yīng)為8位立即數(shù)。 punpckhqdq源操作數(shù)高qword和目的操作數(shù)高qword,并將結(jié)果寫到目的SSE寄存器中。punpcklqdq插入源操作數(shù)低qword和目的操作數(shù)低qword,并將結(jié)果寫到目的SSE寄存器中。源操作數(shù)可以為128位內(nèi)存地址或SSE寄存器。 movntdq使用非臨時提示從SSE寄存器保存壓縮整數(shù)數(shù)據(jù)到內(nèi)存。源操作數(shù)應(yīng)為SSE寄存器,目的操作數(shù)應(yīng)為128位內(nèi)存地址。movntpd 使用非臨時提示從SSE寄存器保存壓縮雙精度數(shù)據(jù)到內(nèi)存。源操作數(shù)應(yīng)為32位通用寄存器,目的操作數(shù)應(yīng)為32位內(nèi)存地址。maskmovdqu使用非臨時 提示從第一個參數(shù)保存選擇位到128位內(nèi)存地址。這兩條指令操作數(shù)都應(yīng)為SSE寄存器,第二個操作數(shù)選擇了那些字節(jié)將從源操作數(shù)寫到目的操作數(shù)。內(nèi)存地址 有DS段中DI(或EDI)寄存器指定,不需要對齊。 clflush寫并且無效指定操作數(shù)地址字節(jié)的緩沖行,指定操作數(shù)必須為8位內(nèi)存位置。 lfence執(zhí)行載入同步。mfence執(zhí)行訪問同步。所以它組合了sfence(上一節(jié)講述的)和lfence指令功能。這些指令沒有任何操作數(shù)。 2.1.17 SSE3指令Prescott技術(shù)發(fā)明了新的指令來提高SSE和SSE2性能 - 稱為SSE3。 fisttp行為和fistp指令相似,并且允許相同操作數(shù),唯一區(qū)別是它總是會截操作,無論當(dāng)前的舍入模式。 movshdup載入目的操作數(shù)為原值同樣尺寸用兩個重復(fù)的高dword填充每一個qword的128位值。movsldup執(zhí)行相同動作,除了它拷貝低dword。目的操作數(shù)應(yīng)為SSE寄存器,源操作數(shù)可以為SSE寄存器或128位內(nèi)存地址。 movddup載入64為源值,賦值它到目的操作數(shù)的高和低qword。目的操作數(shù)應(yīng)當(dāng)為SSE寄存器,源操作數(shù)可以為SSE寄存器或64位內(nèi)存地址。 lddqu是和movdqu執(zhí)行等價功能的指令,但能在源操作數(shù)跨緩沖行邊界時提高性能。目的操作數(shù)必須為SSE寄存器,源操作數(shù)必須為128位內(nèi)存地址。 addsubps執(zhí)行第二和第四組單精度和,第一和第三組單精度差。addsupd執(zhí)行第二組雙精度和,第一組雙精度差。haddps執(zhí)行源和目的 操作數(shù)每個qword的兩個單精度和,保存結(jié)果到目的操作數(shù)低qword,源操作數(shù)結(jié)果到目的操作數(shù)高qword。haddpd對每個操作數(shù)執(zhí)行兩個雙精 度值和,并保存目的操作數(shù)中結(jié)果到目的操作數(shù)的低qword,源操作數(shù)結(jié)果到目的操作數(shù)高qword。所有這些指令都需要SSE寄存器為目的操作數(shù),源操 作數(shù)可以為SSE寄存器或128位內(nèi)存地址。 monitor創(chuàng)建回寫地址行監(jiān)視。它需要三個有順序的操作數(shù)EAX,ECX和EDX。mwait等待回寫到monitor創(chuàng)建的地址區(qū)域。它使用帶有額外參數(shù)的兩個操作數(shù),第一個為EAX,第二個為EDX。2.1.18 AMD 3DNOW!指令3DNow!擴(kuò)展增加新的2.1.14列出MMX指令,并且能操作64位壓縮浮點(diǎn)數(shù)據(jù),每一個有兩個單精度浮點(diǎn)數(shù)據(jù)組成。 這些指令規(guī)則和通用MMX操作相同,目的操作數(shù)必須為MMX寄存器,源操作數(shù)可以為MMX寄存器或64位內(nèi)存地址。pawgusb計(jì)算壓縮無符號字 節(jié)平均值。pmulhrw執(zhí)行帶符號壓縮字的乘積,舍入每一個dword結(jié)果高半部分到目的操作數(shù)。pi2fd轉(zhuǎn)換壓縮dword整數(shù)為壓縮浮點(diǎn)數(shù)。 pf2id使用舍入轉(zhuǎn)換壓縮浮點(diǎn)數(shù)據(jù)為壓縮dword整數(shù)。pi2fw轉(zhuǎn)換壓縮字整數(shù)到壓縮浮點(diǎn)數(shù),只是喲個源操作數(shù)中每個dword的低word。 pf2iw轉(zhuǎn)換壓縮浮點(diǎn)數(shù)據(jù)為壓縮word整數(shù),結(jié)果使用符號擴(kuò)展擴(kuò)展為壓縮浮點(diǎn)數(shù)。pfadd計(jì)算壓縮浮點(diǎn)數(shù)的和。pfsub和pfsubr計(jì)算壓縮浮 點(diǎn)數(shù)的差,第一個用目的值減去源值,第二個用源值減去目的值。pfmul計(jì)算壓縮浮點(diǎn)數(shù)的積。pfacc計(jì)算目的操作數(shù)地和高浮點(diǎn)數(shù)的和,保存結(jié)果到目的 操作數(shù)的低dword,并且計(jì)算源操作數(shù)的低和高dword的和,保存結(jié)果到目的寄存器的高dword。pfnacc用目的操作數(shù)的高浮點(diǎn)數(shù)減去低浮點(diǎn) 數(shù),保存結(jié)果到目的操作數(shù)的低dword,并結(jié)算源操作數(shù)的高和低dword的差,保存結(jié)果到目的操作數(shù)的高dword。pfpnacc用目的操作數(shù)的高 浮點(diǎn)數(shù)據(jù)減去低浮點(diǎn)數(shù)據(jù),保存結(jié)果到目的操作數(shù)的低dword,并計(jì)算源操作數(shù)低和高浮點(diǎn)數(shù)的和,保存結(jié)果到目的操作數(shù)的高dword。pfmax和 pfmin計(jì)算浮點(diǎn)數(shù)的最大和最小值。pswapd翻轉(zhuǎn)源操作數(shù)的高低dword。pfrcp返回原操作數(shù)的近似浮點(diǎn)值倒數(shù)。pfrsqrt返回原操作數(shù) 的開方的近似倒數(shù)。pfrcpit1執(zhí)行第一步Newton-Raphson迭代開方。pfrcpit2計(jì)算第二步Newton-Raphson迭代開 發(fā)。pfcmpeq,pfcmpge和pfcmpgt比較壓縮浮點(diǎn)數(shù)并根據(jù)比較結(jié)果設(shè)置目的操作數(shù)中相應(yīng)數(shù)據(jù)元素的位(全部置為1或置為0),第一個檢查 值是否相等,第二個檢查目的值是否大于或等于源之,第三個檢查是否目的值大于源值。 prefetch和prefetchw從內(nèi)存載入 包含操作數(shù)指定字節(jié)的數(shù)據(jù)行,prefetchw指令必須當(dāng)緩沖行中數(shù)據(jù)被修改時使用,否則應(yīng)使用prefetch指令。操作數(shù)必須為8位內(nèi)存地址。 femms執(zhí)行快速清除MMX狀態(tài)。它沒有操作數(shù)。 2.1.19 x86-64長模式指令AMD64和EM64T體系(我們將使用x86-64作為通用名稱)擴(kuò)展x86指令集以用作64位處理。而原始和兼容模式使用相同的寄存器和指令集。新的長模式擴(kuò)展x86操作64位,并且發(fā)明了一個新的寄存器。你可以使用use64偽指令來生成這個模式的代碼。 每一個通用寄存器都被擴(kuò)展為64位,增加了8個新的通用寄存器和8個新的SSE寄存器。表2.4列出了新增的這些寄存器。通用寄存器的小的尺寸為大的值的低部分。你仍然可以在長模式下訪問ah,bh,ch和dh寄存器,但你不能在新的指令中使用任何新的寄存器。 通常x86體系中任何指令,允許16位或32位操作數(shù)尺寸,在長模式下還允許64位操作數(shù)。64位操作數(shù)必須在長模式下尋址,也允許32位尋址,但不能使用基于16位寄存器的地址。下面為長模式中的mov指令例子: mov rax,r8 ; 傳送64位通用寄存器 mov al,[rbx] ; 傳送通過64位寄存器尋址的內(nèi)存
長模式也使用基于地址的指令指針,你可以手動用RIP指定,但這些地址也能自動由FASM生成,因此在長模式下沒有64位絕對地址。你可以通過中括 號中dword尺寸重寫地址來強(qiáng)制匯編器使用32位絕對地址。也有一個使用64位絕對尋址的例外,它為mov后跟著其中一個為累加器,第二個為內(nèi)存操作數(shù) 的情況。使用qword來強(qiáng)制匯編器使用64位絕對尋址。當(dāng)沒有指定尺寸操作符時,匯編器自動生成最佳格式。 mov [qword 0],rax ; 絕對64位尋址 mov [dword 0],r15d ; 絕對32位尋址 mov [0],rsi ; 自動RIP相對尋址 mov [rip+3],sil ; 手動RIP相對尋址 作為64位操作立即數(shù)只可能為32位數(shù),唯一例外是帶有64位通用寄存器目的操作數(shù)的mov指令。試圖其他指令使用64位立即數(shù)將導(dǎo)致錯誤。 如果在長模式下操作32位通用寄存器的指令,64位寄存器的高32位填充為0.這不同于16位或32位那些指令操作,它們保留高位。 新增三條類型轉(zhuǎn)換指令。cdqe符號擴(kuò)展EAX中dword到qword并保持結(jié)果到RAX。cqo符號擴(kuò)展RAX qword為雙qword并保存額外位到RDX寄存器。這些指令沒有操作數(shù)。movsxd符號擴(kuò)展dword源操作數(shù)到64位目的操作數(shù),源操作數(shù)可以為 32為寄存器或內(nèi)存,目的操作數(shù)必須為寄存器。沒有零擴(kuò)展類似指令,因?yàn)樗詣佑?2位寄存器完成,上一段中說明的那樣。movzx和movsx指令遵守 通常規(guī)則,可以使用64位目的操作數(shù),允許擴(kuò)展字節(jié)或字到qword。 所有二進(jìn)制算術(shù)和邏輯指令提升以允許在長模式下操作64位操作數(shù)。在長模式下禁止使用十進(jìn)制算術(shù)指令。 堆棧操作,比如push和pop在長模式下默認(rèn)為64位操作數(shù),不能使用32位操作數(shù)。pusha和popa在長模式下不可用。 間接near調(diào)整和調(diào)用在長模式下默認(rèn)為64位操作數(shù),它不能使用32位操作數(shù)。另外,間接far調(diào)整和調(diào)用允許任何x86體系允許的操作數(shù),也允 許使用80位內(nèi)存操作數(shù)(僅EM64T實(shí)現(xiàn)了),80位內(nèi)存操作數(shù)有第一個定義偏移的8字節(jié)和指定選擇子的最后兩個字節(jié)組成。長模式下不允許直接far調(diào) 整和調(diào)用。 I/O指令,in,out,ins和outs為例外指令,它們不允許在長模式下操作qword操作數(shù)。但其他串操作可以。他們有新的段格式movsq,cmpsq,scasq,lodsq和stosq。RSI和RDI寄存器默認(rèn)用來尋址這些串元素。 lfs,lgs和lss用來擴(kuò)展以接受80位元內(nèi)存操作數(shù)和64位目的寄存器(僅EM64T實(shí)現(xiàn)了)。lds和les不能在長模式下使用。 系統(tǒng)指令,比如需要48位內(nèi)存操作數(shù)的lgdt,在長模式下需要80為內(nèi)存操作數(shù)。 cmpxchg16b為64位的cmpxchg8b等價指令,它使用雙qword內(nèi)存操作數(shù)和64為寄存器來執(zhí)行類似操作。 swapgs為新增指令,它置換GS寄存器和KernelGSbase MSR寄存器的內(nèi)容(MSR地址為0C0000102h)。 syscall和sysret為新增指令,用來在長模式下提供和sysenter和sysexit相似功能的指令,而sysenter和sysexit在長模式下不允許使用。 |
|