gcc 通过堆栈操作传递参数[重复]

jm81lzqq  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(163)

此问题在此处已有答案

Is it safe or portable in any way (across compilers, platforms, libc implementations etc.) to PUSH extra args in inline asm before a C function call?(2个答案)
21天前关闭。
我有一个非常奇怪的问题。我的目标是用C语言编写面向对象的程序。为此,一个常见的方法是在一个结构体中定义函数指针,并将对调用结构体的显式引用定义为第一个参数:

struct Point {
    int x;
    int y;
    
    int (*sum)(struct Point* p);
};

int sum(struct Point* p) {
    return p->x + p->y;
}

int main() {
    struct Point p;
    p.sum = ∑
    p.sum(&p);
}

但是,我想知道是否可以在没有额外的struct Point*参数的情况下执行此操作。
为此,我需要操作堆栈(可能通过内联汇编)以获得对p的引用,然后可以在sum内部访问该引用。
我目前的想法是在函数调用之前声明一个附加的局部变量,该变量包含对结构的引用

void* ptr = &p;

然后将此值压入堆栈

__asm__("push %rax\n");

但是我不知道如何访问sum函数中的pushed值。我在x86上使用GCC。

xkrw2x1b

xkrw2x1b1#

感谢您的意见。经过一点gdb调试,我能够弄清楚:

#include <stdio.h>

#define GET_SELF_REFERENCE \
    __asm__("movq 16(%rbp), %r8\n" \
            "movq %r8, -8(%rbp)\n");

#define CALL_RESULT(object, method, result) \
    void* __##object = &object; \
    __asm__("push %rax\n"); \
    result = object.method(); \
    __asm__("pop %rax\n");

struct Point {
    int a;
    int b;
    int (*sum)();
};

void function() {
    struct Point* st = NULL;
    __asm__("movq 16(%rbp), %r8\n"
            "movq %r8, -8(%rbp)\n");

    printf("%d\n", st->a);
}

int sum() {
    struct Point* self = NULL;
    GET_SELF_REFERENCE

    return self->a + self->b;
}

int main() {
    struct Point p;
    p.a = 12;
    p.b = 49;
    p.sum = &sum;

    int result;

    CALL_RESULT(p, sum, result)
    printf("%d\n", result);

    return 0;
}

我需要将偏移量16添加到我的rbp中,以获得存储在我的pr变量中的地址。
对于那些想知道我为什么要这样做的人:这只是出于好奇,也是一个大学项目的一部分。我从来没有在生产代码中这样做过,因为它真的很脆弱,本质上是无用的。我只是想实现一个“真正的”面向对象的机制,就像Python中的self参数被隐式地传递给函数一样。

相关问题