IA-32中的傳送指令
IA-32常用指令類型
(1)傳送指令 – 通用數據傳送指令 MOV:一般傳送,包括movb、movw和movl等 MOVS:符號擴展傳送,如movsbw、movswl等 MOVZ:零擴展傳送,如movzwl、movzbl等 XCHG:數據交換 PUSH/POP:入棧/出棧,如pushl,pushw,popl,popw等 –地址傳送指令 LEA:加載有效地址,如leal (%edx,%eax), %eax”的功能為 R[eax]←R[edx]+R[eax],執行前,若R[edx]=i, R[eax]=j,則指令執行后,R[eax]=i+j – 輸入輸出指令 IN和OUT:I/O端口與寄存器之間的交換 – 標志傳送指令 PUSHF、POPF:將EFLAG壓棧,或將棧頂內容送EFLAG
“入棧”(pushw %ax)

“出棧” (popw %ax)

程序由指令序列組成

功能:R[esp]← R[esp]-4,M[R[esp]] ←R[ebp]的實現原理

執行下一個指令

IA-32中的定點算術運算指令
(2)定點算術運算指令 – 加 / 減運算(影響標志、不區分無/帶符號) ADD:加,包括addb、addw、addl等 SUB:減,包括subb、subw、subl等 – 增1 / 減1運算(影響除CF以外的標志、不區分無/帶符號) INC:加,包括incb、incw、incl等 DEC:減,包括decb、decw、decl等 – 取負運算(影響標志、若對0取負,則結果為0且CF清0,否則CF置1) NEG:取負,包括negb、negw、negl等 – 比較運算(做減法得到標志、不區分無/帶符號) CMP:比較,包括cmpb、cmpw、cmpl等 – 乘 / 除運算(不影響標志、區分無/帶符號) MUL / IMUL:無符號乘 / 帶符號乘 DIV/ IDIV:帶無符號除 / 帶符號除
算數運算

IA-32的寄存器組織

功能:R[eax]← R[edx]+R[eax]*1

功能:R[eax]← R[edx]+R[eax]*1 (執行后)

定點加法指令舉例
假設 R[ax]=FFFAH,R[bx]=FFF0H,則執行以下指令后 “addw %bx, %ax” AX、BX中的內容各是什么?標志CF、OF、ZF、SF各是什么?要求分別 將操作數作為無符號數和帶符號整數解釋並驗證指令執行結果。 解:功能:R[ax]←R[ax]+R[bx],指令執行后的結果如下 R[ax]=FFFAH+FFF0H=FFEAH ,BX中內容不變 CF=1,OF=0,ZF=0,SF=1 若是無符號整數運算,則CF=1說明結果溢出 驗證:FFFA的真值為65535-5=65530,FFF0的真值為65515 FFEA的真值為65535-21=65514≠65530+65515,即溢出 若是帶符號整數運算,則OF=0說明結果沒有溢出 驗證:FFFA的真值為-6,FFF0的真值為-16 FFEA的真值為-22=-6+(-16),結果正確,無溢出
定點乘法指令舉例
假設R[eax]=000000B4H,R[ebx]=00000011H, M[000000F8H]=000000A0H,請問: (2) 執行指令“imull $-16, (%eax,%ebx,4), %eax”后哪些寄存器和存儲單元發生 了變化?乘積的機器數和真值各是多少? 解:“imull -16, (%eax,%ebx,4),%eax” 功能為 R[eax]←(-16)×M[R[eax]+R[ebx]×4] ,執行結果如下 R[eax]+R[ebx]×4=000000B4H+00000011H<<2=000000F8H R[eax]=(-16)×M[000000F8H] =(-16)× 000000A0H(帶符號整數乘) =16 × (-000000A0H) =FFFFFF60H<<4 =FFFFF600H EAX中的真值為-2560
x87浮點處理指令
IA-32的浮點處理架構
IA-32的浮點處理架構有兩種 (1) x87FPU指令集(gcc默認) (2) SSE指令集(x86-64架構所用) • IA-32中處理的浮點數有三種類型 – float類型:32位 IEEE 754 單精度格式 – double類型:64位 IEEE 754 雙精度格式 – long double類型:80位雙精度擴展格式 1位符號位s、15位階碼e(偏置常數為16 383)、1位顯式 首位有效位(explicit leading significant bit)j 和 63位 尾數f。它與IEEE 754單精度和雙精度浮點格式的一個重要的 區別是:它沒有隱藏位,有效位數共64位。
x87 FPU指令
x87 FPU 特指與x86處理器配套的浮點協處理器架構 – 浮點寄存器采用棧結構 • 深度為8,寬度為80位,即8個80位寄存器 • 名稱為 ST(0) ~ ST(7),棧頂為ST(0),編號分別為 0~7 – 所有浮點運算都按80位擴展精度進行 – 浮點數在浮點寄存器和內存之間傳送 • float、double、long double型變量在內存分別用IEEE 754單精度、雙精度和擴展精 度表示,分別占32位(4B)、64位(8B)和96位(12B,其中高16位無意義) • float、double、long double類型變量在浮點寄存器中都用80位擴展精度表示 • 從浮點寄存器到內存:80位擴展精度格式轉換為32位或64位 • 從內存到浮點寄存器: 32位或64位格式轉換為80位擴展精度格式
數據傳送類 (1) 裝入 (轉換為80位擴展精度) FLD:將數據從存儲單元裝入浮點寄存器棧頂 ST(0) FILD:將數據從int型轉換為浮點格式后,裝入浮點寄存器棧頂 (2) 存儲(轉換為IEEE 754單精度或雙精度) FSTx:x為s/l時,將棧頂ST(0)轉換為單/雙精度格式,然后存入存儲單元 FSTPx:彈出棧頂元素,並完成與FSTx相同的功能 FISTx:將棧頂數據從int型轉換為浮點格式后,存入存儲單元 FISTP:彈出棧頂元素,並完成與FISTx相同的功能 帶P結尾指令表示操作數會出棧,也即ST(1)將變成ST(0)
數據傳送類 (3) 交換 FXCH:交換棧頂和次棧頂兩元素 (4) 常數裝載到棧頂 FLD1 :裝入常數1.0 FLDZ :裝入常數0.0 FLDPI :裝入常數pi (=3.1415926...) FLDL2E :裝入常數log(2)e FLDL2T :裝入常數log(2)10 FLDLG2 :裝入常數log(10)2 FLDLN2 :裝入常數Log(e)2
算術運算類 (3) 乘法 FMUL/FMULP: 相乘/相乘后彈出棧 FIMUL:按int型轉換后相乘 (4) 除法 FDIV/FDIVP : 相除/相除后彈出棧 FIDIV:按int型轉換后相除 FDIVR/FDIVRP:調換次序相除/相減后彈出棧 FIDIVR:按int型轉換並調換次序相除
IA-32浮點操作舉例




從這個例子可以看出
– 編譯器的設計和硬件結構緊密相關。
– 對於編譯器設計者來說,只有真正了解底層硬件結構和真正
理解指令集體系結構,才能夠翻譯出沒有錯誤的目標代碼,
並為程序員完全屏蔽掉硬件實現的細節,方便應用程序員開
發出可靠的程序。
– 對於應用程序開發者來說,也只有真正了解底層硬件的結構
,才有能力編制出高效的程序,能夠快速定位出錯的地方,
並對程序的行為作出正確的判斷。
