c - 如何告诉gcc不要在堆栈上对齐函数参数?

标签 c assembly gcc calling-convention 68000

我试图将68000处理器的一个可执行文件反编译成C代码,用C函数一一替换原来的子程序。
我面临的问题是我不知道如何让 gcc 使用与原始程序中使用的调用约定匹配的调用约定。我需要将堆栈上的参数打包,而不是对齐。
假设我们有以下功能

int fun(char arg1, short arg2, int arg3) {
    return arg1 + arg2 + arg3;
}
如果我们编译它
gcc -m68000 -Os -fomit-frame-pointer -S source.c
我们得到以下输出
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) :
illustration of the unwanted parameter positioning on the stack
但要使用原始程序,他们需要有地址 4(%sp) , 5(%sp)7(%sp) :
illustration of the desired parameter position
一种可能的解决方案是按以下方式编写函数(处理器为大端):
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;
}
然而,代码看起来很乱,我想知道:有没有办法既保持代码干净又达到预期的结果?

更新:我犯了一个错误。我正在寻找的偏移量实际上是 5(%sp) , 6(%sp)8(%sp) (char-s 应该与 short-s 对齐,但 short-s 和 int-s 仍然被打包):
illustration of the updated desired parameter position
希望这不会改变问题的本质。

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 和汇编代码(用于应用程序、内核、设备驱动程序),所以我对问题空间有些熟悉。

关于c - 如何告诉gcc不要在堆栈上对齐函数参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62600341/

相关文章:

汇编寻址模式

c++ - Hook 内部函数 : How do the the parameters look like?

c++ - 目标失败的 Dev-C++ 配方

c - 如何产生持续的UDP流量?

c - printf 不工作和其他问题

c - 如何计算包含多个 ^= 运算符的表达式?

c - ELF 如何填充它的 `short`?

c - UART无响应

gcc - gcov 符号在哪里?

c++ - 结构方法链接