calling-convention相关内容
C代码: void PtrArg1(int* a,int* b,int* c, int* d, int* e, int* f) { return; } void PtrArg2(int* a,int* b,int* c, int* d, int* e, int* f, int* g, int* h) { return; } 使用 编译 gcc -c -m64 -o
..
我现在正在学习MIPS,我在MIPS绿表上看到,在一个调用中总共保留了12个寄存器(包括s个寄存器)。在我的理解中,必须堆叠所有这样的寄存器,并在以后我们想要再次访问它们时检索它们。 然而,我的问题是,如果经历这个过程有麻烦,为什么还要费心使用这些寄存器呢?除了可能耗尽要使用的寄存器之外,还有使用这些寄存器的意义吗? 推荐答案 MIPS程序集有一个调用约定,该约定指定t寄存器是调用方
..
我试图将以下C代码转换为汇编语言。以下是C代码: typedef struct { int x; int y; } point; int square_distance( point * p ) { return p->x * p->x + p->y * p->y; } 我的汇编代码如下: square_distance: .LFB23:
..
似乎最先进的编译器将堆栈传递的参数视为只读.请注意,在 x86 调用约定中,调用者将参数压入堆栈,而被调用者使用堆栈中的参数.比如下面的C代码: extern int goo(int *x);int foo(int x,int y){咕(&x);返回 x;} 由OS X 10.10中的clang -O3 -c g.c -S -m32编译成: .section __TEXT,__text,r
..
我想了解有关堆栈的更多信息.特别是当调用带有参数的函数时会发生什么.为此,我编写了以下代码: #include 整数总和(整数 d,整数 e,整数 f){整数结果 = d + e + f;返回结果;}诠释主要(无效){int a = 5;诠释 b = 4;诠释 c = 2;int erg = sum(a,b,c);printf("结果是:%d", erg);} 我得到以下汇
..
刚开始学习 x64 汇编,我有一个关于函数、参数和堆栈的问题.据我了解,函数中的前四个参数被传递给 Windows 中的 rcx、rdx、r8 和 r9 寄存器(以及用于浮点数的 xmm0-xmm3).所以一个简单的有四个参数的加法函数看起来像这样: 添加:mov r10, rcx添加 r10, rdx添加 r10, r8添加 r10, r9mov rax, r10ret 但是,我遇到了 文档
..
我们最近尝试将我们的一些 Visual Studio 项目拆分为库,并且在一个测试项目中似乎一切都可以正常编译和构建,其中一个库项目作为依赖项.但是,尝试运行该应用程序给我们带来了以下令人讨厌的运行时错误消息: 运行时检查失败 #0 - ESP 的值未在函数调用中正确保存.这通常是调用使用不同调用约定声明的函数指针的结果. 我们甚至从未为我们的函数指定调用约定(__cdecl 等),将
..
此 C++ 函数的正确 VB6 声明是什么? LPCWSTR* MW_ListReaders(_ULONG Context, int* NumberOfReaders); 以下给了我“错误的 DLL 调用约定": Private Declare Function ListReaders Lib "MyDLL.dll" (ByVal Context As Long, _ByRef Number
..
自从我上次编写 arm assembler 已经有一段时间了,我对细节有点生疏了.如果我从arm调用一个C函数,我只需要担心保存r0-r3和lr,对吧? 如果 C 函数使用任何其他寄存器,它是否负责将这些寄存器保存在堆栈中并恢复它们?换句话说,编译器会为 C 函数生成代码来执行此操作. 例如,如果我在汇编函数中使用 r10,我不必将其值压入堆栈或内存,并在 C 调用后弹出/恢复它,对吗
..
我注意到很多调用约定都坚持为被调用者保留 [e]bx. 现在,我可以理解为什么他们会保留像 [e]sp 或 [e]bp 这样的东西,因为这会弄乱被调用者的堆栈.我也能理解为什么你可能想要保留 [e]si 或 [e]di,因为如果他们不特别小心,这可能会破坏被调用者的字符串指令. 但是[e]bx?[e]bx 到底有什么重要的地方?是什么让 [e]bx 如此特别,以至于多个调用约定坚持在整
..
IA-32 的通用调用约定说: • 被调用者保存寄存器%ebx、%esi、%edi、%ebp、%espCallee 不得更改这些.(或者在返回之前恢复调用者的值.)• 呼叫者保存寄存器%eax, %edx, %ecx, 条件标志如果要保留它们,调用方会保存这些.被叫方可以自由地破坏. 为什么会存在这个奇怪的约定?为什么不在调用另一个函数之前保存所有寄存器?或者让被调用者使用 pusha/pop
..
我正在用 x86 程序集编写一个应该可以从 c 代码调用的函数,我想知道在返回调用者之前必须恢复哪些寄存器. 目前我只恢复esp和ebp,返回值在eax. 是否还有其他我应该关注的寄存器,或者我可以在其中保留任何我喜欢的内容? 解决方案 使用 Microsoft 的32 位 ABI(cdecl 或 stdcall 或其他调用约定)、EAX、EDX 和 ECX 是临时寄存器(调用
..
我正在编写一个将从汇编代码调用的 C 函数. (具体来说,我想在linux内核的系统调用处理路径中做一些检查工作,所以我会在entry_32.S中调度系统调用之前调用c函数) 在定义我的 c 函数时,我对“asmlinkage"修饰符感到困惑. 我知道 asmlinkage 是告诉编译器参数将通过堆栈传递. #define asmlinkage CPP_ASMLINKAGE
..
我目前正在为 Windows 开发一个 C++ 库,它将作为 DLL 分发.我的目标是最大化二进制互操作性;更准确地说,我的 DLL 中的函数必须可以从使用多个版本的 MSVC++ 和 MinGW 编译的代码中使用,而无需重新编译 DLL.但是,我对哪种调用约定最好感到困惑,cdecl 或 stdcall. 有时我会听到诸如“C 调用约定是唯一保证与跨编译器相同的唯一一种"这样的陈述,这与“
..
我在对象中有一个方法,该方法从对象内的多个位置调用.是否有一种快速简便的方法来获取调用此流行方法的方法的名称. 伪代码示例: public Main(){流行方法();}公共 ButtonClick(对象发送者,EventArgs e){流行方法();}公共 Button2Click(对象发送者,EventArgs e){流行方法();}public void PopularMethod(
..
我想将嵌套在类中的 lambda 函数指针传递给 Windows API 回调函数.我发现没有地方可以指定 __stdcall 关键字.有人告诉我编译只支持__cdecl,但是我用nm命令转储obj文件后,发现编译会生成三个辅助函数(__stdcall,>__cdecl, __fastcall) 同时进行.所以我的问题是,如何指定调用约定? 以下代码是我的测试代码. #include "s
..
我们最近尝试将我们的一些 Visual Studio 项目分解为库,并且在以库项目之一作为依赖项的测试项目中,一切似乎都可以正常编译和构建.然而,尝试运行该应用程序给了我们以下令人讨厌的运行时错误消息: 运行时检查失败 #0 - ESP 的值未在函数调用中正确保存.这通常是调用使用不同调用约定声明的函数指针的结果. 我们甚至从未为我们的函数指定调用约定(__cdecl 等),将所有编译
..
我试图理解 System V AMD64 的含义 -ABI 的 调用约定并查看以下示例: struct Vec3{双 x, y, z;};struct Vec3 do_something(void);void use(struct Vec3 * out){*out = do_something();} Vec3 变量是 MEMORY 类型,因此调用者(use)必须为返回的变量分配空间并将其作为
..
int max(int n, ...) 我使用 cdecl 调用约定,调用者在被调用者返回后清理变量. 我想知道宏 va_end、va_start 和 va_arg 是如何工作的? 调用者是否将参数数组的地址作为第二个参数传递给max? 解决方案 如果你看看 C 语言在堆栈上存储参数的方式,宏的工作方式应该就清楚了:- 上位内存地址 最后一个参数倒数第二个参数....第二个
..
我正在尝试在 64 位 Linux 上 GCC 的扩展内联 ASM 中输出相同的字符串两次. int main(){const char* test = "test\n";汇编("movq %[test], %%rdi\n"//调试器显示 rdi = *字符串的地址*"movq $0, %%rax\n""推 %%rbp\n""推 %%rbx\n""调用 printf\n""弹出 %%rbx\n"
..