2015-09-08 114 views
5

我在玩x86 x86,當我試圖使用nasm轉換一些彙編指令到機器指令時,我發現了一些有趣的東西。相同的彙編指令,但不同的機器指令

mov [0x3412],al 
mov [0x3412], bl 
mov [0x3412], cl 
mov [0x3412], dl 

1 00000000 A21234     mov [0x3412], al 
2 00000003 881E1234    mov [0x3412], bl 
3 00000007 880E1234    mov [0x3412], cl 
4 0000000B 88161234    mov [0x3412], dl 

正如你所看到的,mov [0x3412], al是規則的例外。 另外,我發現mov [0x3412], al映射到兩個不同的機器指令。

[email protected]:~/asm$ ndisasm 123 
00000000 88061234   mov [0x3412],al 
00000004 A21234   mov [0x3412],al 

除了這個特殊的指令,還有沒有其他的彙編指令映射到86多臺機器的指令?

+13

你已經偶然發現了英特爾808X設計的神器。 AX是一個通用的16位寄存器,但是英特爾將AX(或AH和AL的高/低8位版本)用於某些操作。英特爾將AX註冊爲累加器。 AX(和AH,AL)對於某些指令有特殊的編碼(通常少用一個字節)。您可以選擇使用較短或較長的指令(對於有限的內存來說越短越好)。除了MOV,AX/AH/AL還爲ADC,ADD,AND,CMP,OR,SBB,SUB,TEST,XOR提供了特殊編碼。 –

+4

@MichaelPetch:這實際上是答案,不是一個簡單的評論! – usr2564301

+3

如果你對這些東西感興趣,你應該看看指令集的參考。 – Jester

回答

11

您正在觀察的是英特爾8088處理器設計考慮因素之一。爲了與8088處理器保持兼容,當今基於x86的處理器推動了一些設計考慮,特別是與指令集相關的。特別是英特爾決定8088應該更高效地利用內存,而犧牲性能。他們創建了一個可變長度的CISC指令集,它有一些特殊的編碼來限制某些指令的大小。這與許多基於RISC的架構(如舊的Motorola 88000)不同,後者使用固定長度的指令,但可以實現更好的性能。

速度與變量或固定長度指令集之間的折衷是因爲處理器需要更多時間來解碼用於實現某些較小指令編碼的複雜可變長度指令。對於英特爾8088來說,情況確實如此。在舊的文獻(大約1980年)中,更好地利用空間的考慮更爲突出。我的答案中的信息與AX寄存器相關,它來自我書架上的一本書,標題爲8088 Assembler Language Programming: The IBM PC,但有些信息可在this等在線文章中找到。

從網上文章這個信息是非常適用於AX(累加器)和其他通用寄存器如BX,CX,DX的情況。

AX是「累加器‘’;

一些操作,如MUL和DIV的,需要一個操作數是在蓄壓器的其他一些操作,例如ADD和SUB,可以施加到任何寄存器的(即,任何八個普通和特殊用途寄存器),但與蓄能器工作時是更有效的。

BX是「基地‘’寄存器;

它是唯一可用於間接尋址的通用寄存器。例如,MOV [BX],AX指令會使AX的內容存儲在地址爲BX的存儲單元中。

CX是「計數 '' 註冊。

的循環指令(LOOP,LOOPE,和LOOPNE),移位和旋轉指令(RCL,RCR,ROL,ROR,SHL,SHR ,SAR)和字符串指令(帶有前綴REP,REPE和REPNE)都使用計數寄存器來確定它們將重複多少次。

DX是「數據‘’登錄;

它與AX爲字大小MUL和DIV操作一起使用時,它也能保持的端口號IN和OUT說明,但它主要是提供一個方便的地方來存儲數據,是所有其他的通用寄存器的。

正如你可以看到英特爾意通用寄存器被用於各種的事情,但他們也可以用於特定目的,並且通常對它們所關聯的說明具有特殊含義。在你的情況下,你正在觀察事實AX被認爲是累加器。英特爾考慮到了這一點,併爲大量指令添加了特殊的操作碼,以更有效地存儲完整的指令。你發現這個與MOV指令(用AX,AL),但它也適用於ADCADDANDCMPORSBBSUBTESTXOR。與AL,AX一起使用時,這些指令中的每一條都具有較短的操作碼編碼,這需要少一個字節。您也可以使用較長的操作碼對AX,AL進行編碼。在你的情況下:

00000000 88061234   mov [0x3412],al 
00000004 A21234   mov [0x3412],al 

是相同的指令,但有兩個不同的編碼。

這是一個很好的HTML x86 instruction set reference,可以在線獲得,但是Intel爲IA-32(i386等)和64位體系結構提供了非常詳細的instruction reference

+2

另一個短形式的操作碼的情況是爲了逐個旋轉,保存'rol/ror/rcl/rcr'的'imm8'字節。由於瘋狂的x86 CISC怪異,根據數據旋轉1套'OF'(溢出標誌),但是由其他計數旋轉使其不確定。這可能只適用於短格式操作碼,而不適用於'C1 C0 01'(長格式'rol eax,1')。根據http://agner.org/optimize/和http://users.atw.hu /instlatx64/GenuineIntel00506E3_Skylake_InstLatX64.txt,英特爾IvyBridge,Haswell和Skylake具有雙倍的長吞吐量。 SandyBridge以兩種形式出現,甚至是'count!= 1'。 –