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