[英]How to tell gcc to not align function parameters on the stack?
我正在嘗試將 68000 處理器的可執行文件反編譯為 C 代碼,將原始子程序一一替換為 C 函數。
我面臨的問題是我不知道如何讓 gcc 使用與原始程序中使用的調用約定相匹配的調用約定。 我需要將堆棧上的參數打包,而不是對齊。
假設我們有以下 function
int fun(char arg1, short arg2, int arg3) {
return arg1 + arg2 + arg3;
}
如果我們編譯它
gcc -m68000 -Os -fomit-frame-pointer -S source.c
我們得到以下 output
fun:
move.b 7(%sp),%d0
ext.w %d0
move.w 10(%sp),%a0
lea (%a0,%d0.w),%a0
move.l %a0,%d0
add.l 12(%sp),%d0
rts
如我們所見,編譯器假定參數的地址為7(%sp)
、 10(%sp)
和12(%sp)
:
但要使用原始程序,他們需要有地址4(%sp)
、 5(%sp)
和7(%sp)
:
一種可能的解決方案是按以下方式編寫 function(處理器為大端序):
int fun(int bytes4to7, int bytes8to11) {
char arg1 = bytes4to7>>24;
short arg2 = (bytes4to7>>8)&0xffff;
int arg3 = ((bytes4to7&0xff)<<24) | (bytes8to11>>8);
return arg1 + arg2 + arg3;
}
但是,代碼看起來很亂,我想知道:有沒有辦法既保持代碼干凈又達到預期的結果?
UPD:我犯了一個錯誤。 我正在尋找的偏移量實際上是5(%sp)
、 6(%sp)
和8(%sp)
(char-s 應該與 short-s 對齊,但 short-s 和 int-s仍然包裝):
希望這不會改變問題的本質。
UPD 2:事實證明,Sierra Systems 的 68000 C 編譯器給出了所描述的偏移量(如在 UPD 中,具有 2 字節對齊)。
但是,問題是關於調整 gcc(或者可能是另一個現代編譯器)中的調用約定。
這是一種打包結構的方法。 我在帶有-m32
的 x86 上編譯它並在反匯編中獲得了所需的偏移量,所以我認為它仍然適用於 mc68000:
typedef struct {
char arg1;
short arg2;
int arg3;
} __attribute__((__packed__)) fun_t;
int
fun(fun_t fun)
{
return fun.arg1 + fun.arg2 + fun.arg3;
}
但是,我認為可能還有更清潔的方法。 這將需要更多地了解生成此類調用序列的其他代碼。 你有它的源代碼嗎?
其他代碼是否必須保留在 asm 中? 使用源代碼,您可以調整 asm 代碼中的偏移量以與現代 C ABI 調用約定兼容。
自 1981 年以來,我一直在 C 中編程,並花了數年時間做 mc68000 C 和匯編代碼(對於應用程序,Z50484C19F1AFDAF3841A0D821ED393D2 有點熟悉問題空間設備驅動程序)。
這不是 gcc 的“故障”,它是 68k 架構,要求堆棧始終在 2 個字節上對齊。 所以根本沒有辦法打破硬件堆棧上的 2 字節 alignment。
但要使用原始程序,他們需要有地址 4(%sp)、5(%sp) 和 7(%sp):
從 ODD memory 地址訪問 word 或 long 值將立即觸發 68000 上的 alignment 異常。
要獲取使用 2 字節 alignment 而不是 4 字節 alignment 傳遞的整數參數,您可以通過-mshort
將默認int
大小更改為 16 位。 您需要將代碼中的所有int
替換為long
(如果您希望它們為 32 位寬)。 執行此操作的粗略方法是將-Dint=long
也傳遞給您的編譯器。 顯然,您將破壞 ABI 對使用-mno-short
編譯的 object 文件的兼容性(這似乎是 gcc 的默認設置)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.