1. 程式人生 > >《深入理解計算機系統》練習題3.13-3.16 set指令 跳轉指令編碼

《深入理解計算機系統》練習題3.13-3.16 set指令 跳轉指令編碼

文章目錄

set指令訪問條件碼

在這裡插入圖片描述
在這裡插入圖片描述
SET指令根據條件碼或者條件碼的組合來將一個位元組設定為0或1(所以如果set指令後面跟的是暫存器,那麼必須是單位元組的暫存器)。
在經過了比較指令a<b,即有t=a-b後,就會根據運算的過程和結果設定條件碼。注意不管是無符號數還是補碼數,t一定是發生溢位後的截斷結果(如果有發生溢位)。
分析有符號數的4種指令。

1)分析setl。因為這個看起來是這四條裡面最簡單的。當SF^OF

為1時(此條指令代表的是a<b,即為1時有a<b),會將D設定為1,否則設定為0。有兩種情況SF^OF為1:
a) SF = 1 OF = 0,此時OF = 0即沒有發生溢位,那麼結果t就是正常結果。SF = 1即結果t是負數,即a-b<0即a<b。符合情況。
b) SF = 0 OF = 1,此時OF = 1即發生了溢位,且SF = 0說明結果t為非負數,所以很明顯這裡是發生的負溢位,所以溢位結果為非負數。a-b>=0這裡負溢位,所以兩個部分都為負,a為負,-b為負,所以b為正,既然a為負,b為正,那兒必有a<b。符合情況。

2)分析setle。既然SF^OF = 1

代表小於且ZF = 1代表等於,那麼(SF^OF) | ZF = 1就代表小於或者等於。

3)分析setge。既然SF^OF = 1代表小於,那麼整體取反後,~(SF^OF) = 1,就代表大於等於。(小於的反面就是大於等於)

4)分析setg。既然(SF^OF) | ZF = 1就代表小於等於,那麼整體取反後,~(SF^OF) & ~ZF = 1(注意取反後或符號變為與符號),就代表大於。

分析無符號數的4種指令。
分析過程跟上面一樣,但這裡書上沒有解釋清楚CF進位標誌的其他作用,導致這裡如果只看書是看不懂的。

CF進位標誌的作用:
1.當兩個數相加時,若最高位向上形成進位,則CF=1;
2.當兩個數相減時,若最高位向上形成借位,則CF=1;
3.當兩個無符號數相乘時,若乘積的高一半為0,則CF=0;
4.當兩個帶符號數相乘時,若乘積的高一半是低一半的符號擴充套件,則CF=0.

以上來自網路。這裡用到了CF進位標誌的第2個作用,既然相減時最高位都借位了,所以a-b<0即a<b.

3.13

在這裡插入圖片描述
每個答案的第一條指令確定了資料型別大小。
第二條指令確定了是否有無符號,具體看答案。
具體分析上面的set指令表格吧:
從sete到setne,可能是無符號數,補碼數,和指標(如果指標,還得看大小是否為指標大小)。
從sets到setns,補碼數(根據答案講解推斷的,如有錯誤請見諒)。
從setg到setle,補碼數。
從seta到setbe,無符號數。

跳轉指令編碼

跳轉指令編碼一般是PC相對的,即目標指令的地址,是由跳轉指令的下一條指令的地址再加上一個地址偏移量得到的。
地址偏移量是,跳轉指令的機器編碼的最高的那個位元組,所代表的補碼數。
在這裡插入圖片描述
每行代表一個指令的機器程式碼,比如第一行,代表的是這條mov指令,這條指令佔了3個位元組,分別是0,1,2這三個位元組,所以這條mov指令的地址為0x0,而下一條jmp指令的地址為0x3。(地址是指指令的開始地址)

下面再來驗證跳轉指令的目標指令地址是如何計算:
看上面機器程式碼的第2行,是jmp跳轉指令,它的最高單位元組為0x03,它所代表的補碼數為3,而下一條指令的地址為0x5,所以目標指令地址=0x5+0x3=0x8。
同理,看第5行的jp跳轉指令,它的最高單位元組為0xf8,它所代表的補碼數為-8,而下一條指令的地址為0xd,所以目標指令地址=0xd-8=0xd-0x8=0x5。

3.15

在這裡插入圖片描述
只看D選項。
先看位元組排序,從左到右是,低位元組地址到高位元組地址。
再看有效位排序,因為是小端法位元組順序,即高有效位在高位元組地址。所以,從左到右是,低有效位到高有效位。
上一章說了,一般取的是高有效位的,而這裡是4個位元組而不是1個位元組,所以偏移量為0xffffff731 0111 0011(利用補碼快速計算)所代表的補碼數-141

cmp指令運算元順序

如果c語句是if(x < y),且x in %rdi , y in %rsi,那麼彙編裡面執行的比較指令為cmp %rsi, %rdi
即比較符號左邊的數放在cmp右邊的運算元,右邊的數放在cmp左邊的運算元。所以可以通過c語句和彙編語句互相確認運算元的左右。
再配合跳轉指令的話,if(x < y)的語句塊就使用jl(代表小於),else的語句塊就使用jge(代表大於等於)。

3.16

在這裡插入圖片描述
這裡解釋下題面的彙編語句:

testq %rsi, %rsi用來檢測p指標是否為空指標,且如果為空指標,那麼將ZF零標誌置為1。

je .L1,如果ZF=1,那麼跳轉到L1,然後直接返回。從c語句來看,因為p為空指標了,條件肯定不成立,然後跳轉到L1,然後直接空操作(因為rep)後結束。

cmpq %rdi, (%rsi),這句注意,由於本來c語句是a > *p,所以這裡本應是cmpq (%rsi), %rdi,但實際上彙編這裡也可以交換位置,那麼這裡實際是*p < a。接著分析,如果*p < a這個條件為假即*p >= a成立,那麼就跳轉到L1,所以這裡用的是jge跳轉(greater and equal)。

3.21

在這裡插入圖片描述
原題不放了,其他地方都好懂,只是testq和jle配合使用感覺很奇怪,但書中並沒有詳細說明test指令到底可能改變哪些條件碼。詳情請看TEST指令——百度百科

將兩個運算元進行按位AND,設結果是TEMP
SF = 將TEMP的最高位賦給SF標誌位,例如結果最高位是1,SF就是1
如果TEMP是0,ZF位置1;如果TEMP不是0,ZF位置0
OF位置0

因為jle指令的跳轉條件是(SF^OF)|ZF,那麼就重點關注TEST指令對這三個條件碼的變化吧。且testq %rsi, %rsi這裡用到的是自測。
所以現在需要驗證,當y小於等於0,能使得跳轉條件(SF^OF)|ZF為1:
1)當y=0.(0^0)|1 = 1,驗證成功。
2)當y<0.(1^0)|0 = 1,驗證成功。
3)當y>0.(0^0)|0 = 0,順便驗證第三種條件,發現小於等於的反面情況會使得跳轉條件為0,反向驗證成功。
所以當y小於等於0時,會執行jle指令然後進行跳轉。

同時這裡也說明了,用test指令來測試一個暫存器與0的關係時(大於等於小於)(而且這裡特指兩個運算元是同一個的情況),小於和等於必須放在一起,大於單獨放。即使用jlejg