最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Intel CPU中的條件轉移指令

2023-08-05 22:20 作者:Login255  | 我要投稿

概述

毫無疑問,Intel CPU功能越來越強大,指令越來越復雜。

從Intel官網(wǎng)可以免費下載其全套CPU手冊。這套手冊是Intel匯編最權威的資料,而且可讀性非常高,對于學習匯編語言,了解CPU工作原理來說,都是最有價值的資料,沒有之一。

本文以《Intel 64 and IA-32 Architectures Software Developers Manual Volume 2 - Instruction Set Reference》為底稿,整理總結一下各種條件轉移指令。

定義

條件轉移指令,常見的有je,jnz,jcxz,jle等,是滿足條件時進行跳轉的指令。

手冊中列出的條件轉移指令總計有95條,記憶很不方便。

CPU的無記憶特性

CPU是沒有記憶的,它只知道按指令功能嚴格執(zhí)行完當前指令,然后繼續(xù)執(zhí)行下一條指令。假設某一種簡單CPU只有四條指令,分別是向上、向下、向左、向右。那么下圖左側的程序運行起來以后,便可以得到右側的運行結果。生成一條從A到B的路徑。但任何一個時刻,你問CPU上一步從哪里來,上一條指令是什么?上一步寄存器內容是多少?它全然不知。

虛擬程序

條件判斷依據(jù)?

典型的條件轉移指令上下文如下(紅色為標號,可以忽略):

L1:? mov eax, 0xFF

L2:? cmp eax, dword ptr [ebp-20h]

L3:? jne?error

L4:? jmp continue

error: return

continue: ......

上面的程序中,L1處的指令將0xFF傳送到寄存器eax,L2處的指令對eax的值和[epb-20]所指向內存中的雙子進行比較,L3處的指令jne意思是:如果不相等,就跳轉到error標號處(jump if not equal)。不過,問題來了:

前面說過,CPU沒有歷史記憶,CPU在執(zhí)行條件轉移指令時,并不知道其上一條指令到底是相減、相加還是相乘或按位與操作,也不知道eax中到底是有符號數(shù)還是無符號數(shù),比如,把cmp換成test或者add,程序依舊可以順利通過編譯并順利運行:

test eax, dword ptr [ebp-20h]

add eax, dword ptr [ebp-20h]

但這種情況下,我們再將jne理解為兩數(shù)不等,就完全不合乎實際程序邏輯了。

事實上,條件轉移指令執(zhí)行時,并不依賴于上一條指令,僅依據(jù)當前EFLAGS寄存器的值進行是否轉移的判定。

關于EFLAGS寄存器

對于IA-32架構CPU,其內部的EFLAGS寄存器布局如下圖所示:

CPU中的標志與控制寄存器EFLAGS

影響EFLAGS寄存器的因素有很多,可以通過指令,如:LAHF, SAHF, PUSHF, PUSHFD, POPF, POPFD, CLI, STD等,任務切換時EFLAGS被保存在TSS中,任務恢復時EFLAGS也被恢復;中斷和異常發(fā)生時,EFLAGS也需要保存和恢復。當然,這些聽不懂也沒關系。

和條件跳轉指令緊密相關的是被稱為狀態(tài)標志的6個標志,分別是CF/PF/AF/ZF/SF/OF

這些標志位都會受到數(shù)學運算指令的影響,如加減乘除、移位、位運算等等。其中最難區(qū)分的是CF和OF,兩個標志都和溢出有關。

從上面的英文畫線部分看,CF標志是針對unsigned?integer運算,而OF是針對signed運算,不過實際上遠沒有這么簡單。比如mul是無符號乘法指令,但其結果會同時影響OF和CF兩個標志,具體細節(jié)是:

比如,兩個十六位數(shù)進行MUL乘法運算,結果保存到dx:ax寄存器對中。如果dx寄存器是0,則OF和CF均為0,否則都為1,而ZF,AF,PF則屬于未定義。針對IMUL有符號數(shù)乘法,影響還要更復雜些。所以具體情況一定要查手冊才能確定。

不過,條件轉移指令的前一條指令,最常見的就是減法SUB,比較CMP和測試TEST,其中cmp和sub的唯一區(qū)別在于:cmp相減的結果不保存,只影響標志位。另外,cmp和sub均同時測試有符號數(shù)和無符號數(shù),因為如果部考慮最高位的溢出,有符號和無符號相減運算的結果是相同的。舉例:

假設:ax = 0x80F0,bx = 0x8F00,那么sub ax, bx對EFLAGS的影響就是:

CF = 1, ZF = 0, SF = 1, OF=0,具體分析如下:

1)假設ax和bx中存儲的都是無符號數(shù),則有:0x80F0可轉換成十進制33008,0x8F00轉換成十進制是36608,那么無符號減法 33008-36608 = -3600,轉換成十六進制為F1F0,做減法運算過程中需要最高位借位。

2)?假設ax和bx中存儲的都是有符號數(shù),那么0x80F0對應十進制-32528,而0x8F00對應十進制-28928,則-32528 - (-289282) = -3600,而且數(shù)據(jù)不超過十六位二進制可以容納的范圍,未發(fā)生溢出,所以OF = 0

通過以上分析我們知道,對于CPU來說,SUB指令無需區(qū)分操作數(shù)是否有符號,只需按無符號數(shù)相減,如果最高位有借位,就置位CY,否則CY=0。然后再按有符號計算一下結果是否溢出,相應置位或復位OF。sub和cmp運算,根據(jù)結果會影響OF, SF, ZF, AF, PF, CF標志。

對于test指令來說,它使兩個操作數(shù)按位進行與運算,影響SF, ZF, PF標志位,且OF=0, CF=0,運算結果不存儲。


Intel CPU的條件轉移指令速記

95個有條件轉移指令,想要記住很難,即便自己不寫,讀別人程序總歸需要理解正確才行。

其實,很多條件轉移指令可以望文生義的,如:

jnz = jump not ZF(如果ZF不為1則轉移)

jle = jump if less or equal (小于或等于轉移)

jb = jump if below (小于則轉移)

不過正如前文所述,CPU是沒有記憶能力的,這里的所謂“等于”,“小于”等,都是基于前一條影響標志位的指令是sub或cmp的假設,如果不是,則根本就風馬牛不相及了。何況below和less是否有區(qū)別也不清楚。

正因為Jxx類條件轉移指令只根據(jù)EFLAGS當前值做出是否轉移的決定,實際上還是需要熟記je是判斷那個標志位,jl是判斷哪個標志位。根據(jù)Intel手冊,有如下主要規(guī)律:

這里,SF與運算結果最高位相同,對于有符號數(shù)來說,SF=1則是負數(shù),否則是正數(shù);而OF則代表是否存在溢出,也就是目的操作數(shù)能否裝下完整運算結果。結合這兩個因素仔細一想,上面通過SF和OF是否相等來判斷兩個有符號數(shù)大小的方法真的很巧妙。

只有明白了每條指令對標志位的影響,再明白了每一條條件轉移指令到底是根據(jù)哪個標志位或標志位組合來判斷,才算是真正搞懂了條件轉移。

最后,將所有條件轉移指令列表如下:


Intel CPU中的條件轉移指令的評論 (共 條)

分享到微博請遵守國家法律
河池市| 原平市| 蕲春县| 格尔木市| 海安县| 漠河县| 通化市| 邹城市| 肥城市| 石泉县| 吉木萨尔县| 交城县| 南安市| 崇信县| 太和县| 怀集县| 临洮县| 松阳县| 永修县| 华坪县| 渝中区| 涟水县| 皮山县| 名山县| 阳谷县| 宁化县| 治多县| 新民市| 通榆县| 眉山市| 金坛市| 渝中区| 广宁县| 凉城县| 新竹县| 佛教| 澄江县| 神农架林区| 龙里县| 镇原县| 固原市|