在C中模拟thiscall以实现struct函数而无需自引用

前端之家收集整理的这篇文章主要介绍了在C中模拟thiscall以实现struct函数而无需自引用前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这与一系列面向对象的C贴子有关,但不同之处在于我不想要所有的功能,只需要一个:

能够做到这一点:

struct foo { 
  int (*bar)(void);
  char baz;
};

然后有一个反向引用. C有一个名为cdecl的调用约定;基本上将参数推送到堆栈,有一个返回指针,然后跳转到某个地址.该地址的代码从堆栈中弹出参数并继续它的快乐方式.

thiscall约定略有不同,因为它隐式地添加了一个额外的参数,一个“this”指针.

因为你可以很容易地在C中开始执行任意字节代码并且由于gcc支持内联汇编程序模板化,这听起来像你可以制作一些宏以便你可以做类似的事情:

int bar(void) {
  GETTHIS;
  cThis->baz = 0;
}

int createFoo(struct Foo*pFoo) {
  ASSIGN(pFoo,bar);
}

基本上ASSIGN会做的是回避cdecl来模仿一个thiscall样式约定,然后GETTHIS会做的是会计技巧的另一面.

我想知道是否:

>存在和解决方
>如果没有,如果有一个原因导致无法完成

只有这一点;真正的“我们所有人都同意成年人”风格的会员功能,简直太棒了.谢谢!

笔记:

>我只是在谈论x86,linux,gcc ……我知道世界是一个广阔而陌生的地方.
>这纯粹是出于好奇.

解决方法

第一次小修正:

C has a calling convention called cdecl; basically pushes arguments on
to the stack,has a return pointer,then jumps to some address. The
code at that address pops arguments off the stack and goes on its
merry way.

调用者不会从堆栈中弹出参数.它会读取参数而不会从堆栈中弹出它们.相反,堆栈由调用者清除.这是因为在cdecl约定中,被调用者不知道参数的确切数量.

现在,关于你的问题.没有严格定义的thiscall调用约定.更多信息here.

GCC-具体:

thiscall is almost identical to cdecl: the calling function cleans the
stack,and the parameters are passed in right-to-left order. The
difference is the addition of the this pointer,which is pushed onto
the stack last,as if it were the first parameter in the function
prototype

你无法隐藏额外的这个参数并在函数体内检索它,特别是因为这是第一个函数参数.如果隐藏它 – 所有其他功能参数将被移位.相反,你可以(并且应该恕我直言)将它声明为第一个函数参数,并且你可以直接访问它,而不需要额外的技巧:

int bar(struct foo *cThis) {
  cThis->baz = 0;
}

MSVC特有的:

… the this pointer is passed in ECX and it is the callee that cleans
the stack,mirroring the stdcall convention used in C for this
compiler and in Windows API functions. When functions use a variable
number of arguments,it is the caller that cleans the stack (cf.
cdecl).

在这里,您可以通过将ECX寄存器的值复制到本地变量来实现技巧.像这样的东西:

#define GETTHIS \
struct foo *cThis; \
_asm { \
    mov cThis,ecx \
};

然而,这很棘手,可能并不总是有效.原因是根据thiscall / stdcall调用约定,ECX寄存器保留用于函数,因此编译器可能生成覆盖ECX寄存器值的代码.这甚至可能在您调用GETTHIS宏之前发生.

猜你在找的C&C++相关文章