2013-12-12 51 views
0

我已經在x86-64程序集(AT & T)語法中編寫了一個小程序,它的組裝非常好,但是我沒有得到我期望的結果。 我有一個變量在寄存器%rdi,我需要修改一個子程序,我需要保留一些其他用法的原始值以後。我想要做的是將push原始值寫入堆棧,然後在子例程結束時再次檢索它,例如,如果變量位於%rdi中。將變量保存到堆棧(X86-64程序集)

pushq %rdi 
    call subroutine 
    movq (%rsp), %rdi 

現在,我不確定這是否是正確的方法嗎?我在某處讀過一個子例程將返回值推入堆棧,但這是否意味着我在嘗試檢索變量時必須包含偏移量?

而且我知道我必須保持爲16個字節,這我不太清楚,如果我做對齊堆棧指針。如果我不這樣做,彙編程序會給我一個錯誤,或者這可能是我的程序失敗的原因?

順便說一下,這個程序是一個任務的一部分,所以我不能與你分享代碼,但我希望我的描述足夠好。

+0

無法想象你的任務如此祕密,以至於無法共享代碼。 – Artur

+0

這不是什麼祕密,但是如果在網站上發佈整個程序並要求其他人糾正所有錯誤,那麼我就處於作弊的邊緣。 – user680881

回答

0

的代碼片段是,它未能跟上整個通話序列中,這可能不是預期的行爲平衡堆棧指針可疑。通常,您可以匹配pushpop操作,push多次,然後addq $k, %rsp(其中k是前面的每個push的組合大小),或者在整個函數的執行過程中保持幀大小恆定並使用顯式訪問。

既然你需要不斷保持對齊堆棧指針16字節,保持一個固定大小的框架可能是最直接的方法。它看起來像

# in the function prologue 
subq $K, %rsp 
... 
mov %rdi, SLOT(%rsp) 
call subroutine 
mov SLOT(%rsp), %rdi 
... 
# in the epilogue 
addq $K, %rsp 

哪裏K足夠的空間讓所有本地堆棧狀態加上最大的一組輸出參數有足夠的空間,四捨五入爲16,和SLOT是堆棧上的一個點的值保留的%rdi

整數類型的返回值通常放在rax中,而不是堆棧中。其他類型以不同的方式返回(例如通過隱藏的指針) - 檢查您正在與之交互的編譯器的調用約定。

+0

好的,所以根據我的理解你的答案,下面的代碼將做到這一點? SUBQ $ 16%RSP MOVQ%RDI 8(%RSP) 調用子程序 MOVQ 8(%RSP),%RDI addq $ 16%RSP – user680881

+0

對不起我的代碼是有點難以閱讀。希望沒關係 – user680881

+0

這對我來說看起來不錯,儘管通常爲整個函數使用一個「subq/addq」對,而不是每個子例程調用的一對。 – gsg

0

相反的movq (%rsp),%rdi,使用popq %rdi。第一個不會更新RSP堆棧指針,因此在返回調用您的函數時可能會遇到問題。

這,當然,如果subroutine不調整堆棧本身。它subroutine正在使用standard (Pascal) calling convention,參數將被該函數本身刪除,而不是調用者,並且您將無法訪問保存的%rdi值。