我在這本教科書上,Randal E. Bryant, David R. O'Hallaron - Computer Systems. 程式設計師的觀點[第三版](2016年,培生)
。
我被卡住了,不知道作者是如何算出開關表的案例編號的,如下圖所示~
我不知道的是,作者是如何算出開關表的案例編號的?
我不確定的是他們是如何獲得案例編號的,比如案例A是案例5:以及案例2/7是案例C和案例D,以及這個例子中的其他案例,等等
希望得到任何幫助,謝謝!
首先,你的書有一個錯誤--它說"a在%rsi,b在%rdi"--但這不是標準x64呼叫慣例,它與其他匯編不一致。
該書的含義:
%rdi->a,%rsi->b,%rdx->c, and%rcx->dest
繼續,讓我們了解一下會發生什么:
默認的代碼塊前兩個操作代碼是:cmpq $7, %rdi
ja .L2
ja是上面的跳轉if,即如果a > 7則轉到.L2--這是在匯編的最后。我們可以推斷出這是default代碼塊(它立即繼續到函式的結尾)--在.L2下我們有:
movq %rsi, %rdi
movq %rdi, %(rcx) ; 這對應于C語言中的*dest = val
所以我們可以得出結論,%(rcx)在這種情況下得到%rsi的值--換句話說,在默認的代碼塊中,val = b。
切換代碼塊如果我們上面的第一個
ja沒有切除,那么我們jmp *.L4(,%rdi,8)/code>。由于a不在7以上,我們有八個可能性--我們可以在.L4表中看到:
- 如果
a == 0,那么我們跳到.L3 。
- 如果
a == 1, a == 3, 或a == 6, 我們跳到.L2 (我們的默認代碼塊, 上面有描述)
- 如果
a == 2或a == 7我們跳到.L5 。
- 如果
a == 4,我們跳到.L6 。
- 如果
a == 5,我們跳到.L7 。
.L3,或案例0
。
這個塊運行leaq 112(%rdx), %rdi,它的作用是將%rdi設定為%rdx 112 - 也就是c 112。然后我們跳到函式的結尾--我們可以得出結論,在case 0代碼塊中,val = c 112。
.L7,或案例5
。
這個代碼塊運行leaq (%rdx, %rsi), %rdi,它將%rdi設定為%rdx %rsi(也就是c b)- 然后呼叫salq $2, %rdi,它只是將這個值左移了2位- 總值為(c b)<< 2。然后我們跳到函式的結尾--我們可以得出結論:val = (c b) << 2在case 5代碼塊中。
。
.L6,或案例4
。
在這里,我們已經立即跳到了函式的末尾,只是呼叫了movq %rdi, (%rcx)操作碼--這實際上等同于設定*dest = a。我們可以得出結論,在這種情況下,val = a.
。
.L7,或案例5這個塊運行xorq $15, %rsi - 這相當于b ^= 15。然后運行movq %rsi, %rdx - 將c設定為這個值。然后我們繼續直接進入上面描述的.L3--它設定val=c 112。我們可以得出結論,.L7是我們的落地開關案例。
一般來說,反轉開關情況是非常簡單的--它主要涉及到理解跳轉表如何對應于比較暫存器中的不同值(注意這里a的幾個可能值如何映射到表中的同一個跳轉)--以及理解不同開關情況之間的落差。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/322475.html
標籤:
上一篇:使用帶有標記粘貼運算子的宏



