首頁>Club>
反彙編時往往看到c語言函式呼叫的對應彙編程式碼fp指標,搜尋了一些文章說fp是指向回溯結構列表的最後一個結構,但是還是不怎麼理解
3
回覆列表
  • 1 # 繁星落石

    C語言的執行是在程序棧上,函式呼叫、引數等等會被壓入棧,成為棧幀。因為是按照執行順序入棧的,所以遍歷棧就可以得到之前所經歷的所有函式(已執行完的不會保留)。

    幀指標指向的就是棧頂的位置,因為棧在記憶體裡是向下生長的,所以需要棧頂指標來標識棧生長到了哪裡,如果發生程式崩潰或者需要列印backtrace/calltrace,可以透過棧頂向棧底查詢,並將遍歷內容打印出來。

  • 2 # 碼哥位元

    直接引用一個編譯產生的彙編片段作為例子吧:

    0000822c <func>:

    822c: e52db004 push {fp} ; (str fp, [sp, #-4]!)

    8230: e28db000 add fp, sp, #0

    8234: e24dd014 sub sp, sp, #20

    8238: e50b0010 str r0, [fp, #-16]

    823c: e3a03002 mov r3, #2

    8240: e50b3008 str r3, [fp, #-8]

    8244: e51b3008 ldr r3, [fp, #-8]

    8248: e51b2010 ldr r2, [fp, #-16]

    824c: e0030392 mul r3, r2, r3

    8250: e1a00003 mov r0, r3

    8254: e24bd000 sub sp, fp, #0

    8258: e49db004 pop {fp} ; (ldr fp, [sp], #4)

    825c: e12fff1e bx lr

    00008260 <main>:

    ...... 不引全了

    這裡可以看到,在函式func中,首先執行了將fp入棧的操作,其目的就是為了儲存外層caller(也就是main函式中)的fp內容。然後將fp內容設定為sp(上一步push導致sp有所改變)。然後將sp自減,用來騰出引數和自動變數(儲存在棧中)的空間。中間有些賦值和乘法操作我們忽略。看到最後三行(8254開始的地方),函式返回前修改sp為fp的值,這是在將sp恢復到剛進入函式後push完的位置。之後pop fp將fp的值恢復成caller(main中)中的值。最後跳轉回caller中的下一條指令上。

    可以看到,fp是用來標識棧底位置的,這裡有兩個好處:

    有了fp的存在,我們不需要執行一堆的push指令將需要儲存在棧上的變數先入棧佔位,而是直接操作sp即可,因為棧底有fp已經儲存好了。後續對棧中變數賦值則直接透過fp減一個偏移即可,節省不必要的push開銷。

    便於跟蹤除錯函式棧情況,有了fp和sp的存在,很容易定位到被呼叫函式(callee)的棧幀區域,便於偵錯程式進行除錯。

  • 中秋節和大豐收的關聯?
  • 矮個子適合穿馬丁靴嗎?