标签: calling-convention

在未命名的命名空间中定义的C回调函数?

我有一个使用C bison解析器的C++项目.C语法分析器使用函数指针的结构来调用函数,这些函数在生产被bison减少时创建正确的AST节点:

typedef void Node;
struct Actions {
  Node *(*newIntLit)(int val);
  Node *(*newAsgnExpr)(Node *left, Node *right);
  /* ... */
};
Run Code Online (Sandbox Code Playgroud)

现在,在项目的C++部分,我填写了这些指针

class AstNode {
  /* ... */
};
class IntLit : public AstNode { 
  /* ... */
};

extern "C" {
  Node *newIntLit(int val) {
    return (Node*)new IntLit(val);
  }

  /* ... */
}

Actions createActions() {
  Actions a;
  a.newIntLit = &newIntLit;
  /* ... */
  return a;
}
Run Code Online (Sandbox Code Playgroud)

现在我把它们放在其中的唯一原因extern "C"是因为我希望它们具有C调用约定.但最佳的是,我希望他们的名字仍然受到损害.它们永远不会从C代码中调用,因此名称重整不是问题.使它们受损会避免名称冲突,因为有些动作被称为error,并且C++回调函数具有丑陋的名称,如下所示只是为了避免与其他模块的名称冲突.

extern "C" {
  void uglyNameError(char const *str) …
Run Code Online (Sandbox Code Playgroud)

c++ calling-convention linkage

6
推荐指数
1
解决办法
1157
查看次数

使用调用约定fastcall的任何真实用例?

你有没有使用调用约定fastcall的真实用例?

谢谢.

c++ stack calling-convention

6
推荐指数
2
解决办法
1188
查看次数

为什么使用错误的调用约定有时会起作用?

我使用"StartServiceCtrlDispatcher"函数在windows中注册一个回调函数(称为ServiceMain),但我声明的回调函数是用错误的调用约定编译的.

问题是,在某些计算机上,当应用程序从回调函数返回时,应用程序崩溃,但在其他计算机上,应用程序没有崩溃.

现在,一旦我发现bug一切正常,但我只是不明白为什么在某些计算机上它能正常工作而不会崩溃?

谢谢!:-)

c++ winapi callback calling-convention

6
推荐指数
1
解决办法
683
查看次数

AVX寄存器如何通过公共调用约定处理?

我找不到任何定义调用者和被调用者如何处理YMM寄存器的文档.

为了集中我的问题,这是我想知道的:

  1. 在返回调用者之前,被调用者必须恢复哪些YMM寄存器?
  2. 由于Linux和Windows中的XMM寄存器存在差异,我假设YMM寄存器也遵循相同的规则.每个操作系统的规则是什么?

编辑:感谢下面的答案,我能够在提到的Win64文档中找到答案.我很确定Linux遵循类似的规则:

"...
The YMM registers do not have callee-save status, except for the lower half
of YMM6-YMM15 in 64-bit Windows, where XMM6-XMM15 have callee-save status.
Possible future extensions of the vector registers to 512 bits or more will not have calleesave
status.
..."
Run Code Online (Sandbox Code Playgroud)

linux windows calling-convention avx

6
推荐指数
1
解决办法
863
查看次数

理解C反汇编的电话

我想学习C调用约定.为此,我编写了以下代码:

#include <stdio.h>
#include <stdlib.h>

struct tstStruct
{
    void *sp;
    int k; 
};

void my_func(struct tstStruct*);

typedef struct tstStruct strc;

int main()
{
    char a;
    a = 'b';
    strc* t1 = (strc*) malloc(sizeof(strc));
    t1 -> sp = &a;
    t1 -> k = 40; 
    my_func(t1);
    return 0;   
}

void my_func(strc* s1)
{
        void* n = s1 -> sp + 121;
        int d = s1 -> k + 323;
}
Run Code Online (Sandbox Code Playgroud)

然后我使用GCC使用以下命令:

gcc -S test3.c
Run Code Online (Sandbox Code Playgroud)

并想出了它的装配.我不会显示我得到的整个代码,而是粘贴函数my_func的代码.就是这个:

my_func:
.LFB1:
.cfi_startproc
pushq   %rbp
.cfi_def_cfa_offset 16 …
Run Code Online (Sandbox Code Playgroud)

c assembly x86-64 calling-convention att

6
推荐指数
2
解决办法
6309
查看次数

从64位asm调用Printf时,params如何通过?

我正在学习再次使用汇编语言,到目前为止我遇到的唯一问题就是调用C语言.我所拥有的书是32位,而我的工作是64位.显然,调用约定存在很大差异,并且http://www.x86-64.org/documentation站点已关闭.因此,经过一些挖掘/测试,在C中编译虚拟程序并花费3天时间,我想我会发布我的发现,如果它可以帮助其他人.

RAX是否需要给出浮点数?堆栈填充"阴影空间"16或32位?这个宏用于对齐小程序的堆栈是否可以通过?我知道你可以用对齐NOP填充代码,我不确定堆栈框架.

; pf.asm compiled with 'nasm -o pf.o -f elf64 -g -F stabs'
; linked with 'gcc -o pf pf.o'
; 64-bit Bodhi (ubuntu) linux

%include "amd64_abi.mac"
[SECTION .data]
First_string:   db "First string.",10,"%s", "%d is an integer. So is %d",10
                db "Floats XMM0:%5.7f  XMM1:%.6le  XMM2:%lg",10,0  
Second_String:  db "This is the second string... %s's are not interpreted here.",10
                db " Neither are %d's nor %f's. 'Cause it is a passed value.", 10, 0
; Just a regular string …
Run Code Online (Sandbox Code Playgroud)

assembly printf x86-64 abi calling-convention

6
推荐指数
1
解决办法
5268
查看次数

在C中以相反的顺序传递参数有什么意义?

在C中进行函数调用时,参数以相反的顺序传递.这很重要,这样我们就可以访问第一个参数.而这一些如何支持varargs.我不明白即使你有权访问第一个参数,你仍然需要知道函数有多少个参数,否则你可能很容易忽略最后一个参数并开始将无效值视为参数.

如果参数count是必需的,那么以相反的顺序传递参数是没有意义的,因为你可以使用(sp - 2*number_of_arguments,sp = stack pointer)访问第一个参数.

以相反的顺序传递参数也应该有助于递归调用,我不明白如何.

先感谢您.

c stack callstack function calling-convention

6
推荐指数
1
解决办法
2091
查看次数

如何使用单个GCC(交叉)编译器(交叉)编译到ARM硬件和软件浮点(softfp)?

我想使用单个(交叉)编译器来编译不同ARM调用约定的代码:因为我总是想使用浮点和NEON指令,我只想选择硬浮点调用约定或软浮点数(softfp)调用约定.

我的编译器默认为hard-float,但它支持我需要的两种架构:

$ arm-linux-gnueabihf-gcc -print-multi-lib
.;
arm-linux-gnueabi;@marm@march=armv4t@mfloat-abi=soft
$
Run Code Online (Sandbox Code Playgroud)

当我使用默认参数进行编译时:

$ arm-linux-gnueabihf-g++ -Wall -o hello_world_armhf hello_world.cpp
Run Code Online (Sandbox Code Playgroud)

它成功没有任何错误.

如果我使用-print-multi-lib返回的参数进行编译:

$ arm-linux-gnueabihf-g++ -marm -march=armv4t -mfloat-abi=soft -Wall -o hello_world hello_world.cpp
Run Code Online (Sandbox Code Playgroud)

它再次编译没有错误(顺便说一句,我如何测试结果代码是硬浮动还是软浮动?)

不幸的是,如果我试试这个:

$ arm-linux-gnueabihf-g++ -march=armv7-a -mthumb-interwork -mfloat-abi=softfp -mfpu=neon -Wall -o hello_world hello_world.cpp
[...]/gcc/bin/../lib/gcc/arm-linux-gnueabihf/4.7.3/../../../../arm-linux-gnueabihf/bin/ld: error: hello_world uses VFP register arguments, /tmp/ccwvfDJo.o does not
[...]/gcc/bin/../lib/gcc/arm-linux-gnueabihf/4.7.3/../../../../arm-linux-gnueabihf/bin/ld: failed to merge target specific data of file /tmp/ccwvfDJo.o
collect2: error: ld returned 1 exit status
$
Run Code Online (Sandbox Code Playgroud)

我已经测试了一些参数的其他排列,但似乎除了-print-multi-lib所示的组合之外的任何其他结果都会导致错误.

我读过ARM编译错误,VFP注册使用的是可执行文件,而不是目标文件,但问题是二进制文件的某些部分是软的,有些是硬浮动的.我有一个C++文件来编译...

我错过了哪些参数可以用-march = armv7 -a -mthumb-interwork -mfloat-abi = softfp …

gcc arm calling-convention

6
推荐指数
1
解决办法
2万
查看次数

64位C++传递具有"不同"调用约定作为参数的函数会产生不明确的错误

我的目标是使用__cdecl和__stdcall调用约定轻松提取任意函数的原型.它在32位工作正常.唯一改变的是模板函数参数中的调用约定.

根据维基百科的说法: "在Windows环境中编译x64架构时(无论是使用Microsoft还是非Microsoft工具),只有一个调用约定 - 这里描述的那个,所以stdcall,thiscall,cdecl,fastcall等. ,现在都是一样的."

这打破了64位的代码.即使调用约定相同,将函数作为参数传递仍然需要使用正确的命名法.IE如果函数定义为__stdcall,则必须将其传递给接受__stdcall的包装器.即使__cdecl相同,您仍然必须将定义为__cdecl的函数传递给接受__cdecl的包装器.

以32位工作的示例:

template<typename T, typename... Args>
struct WrapperSTD { typedef T(__stdcall *Functor)(Args...); };

template<typename T, typename... Args>
struct WrapperC { typedef T(*Functor)(Args...); };

template<typename T, typename... Args>
WrapperSTD<T, Args...> wrap(T(__stdcall *func)(Args...)) {
    return WrapperSTD<T, Args...>{};
}
template<typename T, typename... Args>
WrapperC<T, Args...> wrap(T(*func)(Args...)) {
    return WrapperC<T, Args...>{};
}
Run Code Online (Sandbox Code Playgroud)

我的目标是能够运行,例如:

using MsgBoxProto = decltype(wrap(MessageBoxA))::Functor;
Run Code Online (Sandbox Code Playgroud)

这适用于32位.但是,由于__stdcall和__cdecl在x64中显然是相同的,因此它不能在64位中工作并引发错误,表示调用是不明确的.它还告诉我模板已经定义.直观地说,似乎我能够将带有__cdecl的函数传递给这个__stdcall函数,因为编译器认为它们是相同的.但是,这不起作用:

template<typename T, typename... Args>
struct WrapperFC { typedef T(__stdcall *Functor)(Args...); };

template<typename T, typename... Args>
WrapperFC<T, Args...> wrap(T(__stdcall …
Run Code Online (Sandbox Code Playgroud)

c++ 64-bit cdecl calling-convention stdcall

6
推荐指数
1
解决办法
870
查看次数

经常使用r10和r11的可接受性

我最近做了很多x64汇编编程(在Linux上),用于与我的C/C++程序集成.

由于我主要关心效率,我喜欢尽可能少地使用不同的寄存器/存储器地址,以及尝试不创建任何堆栈帧或保留寄存器(每个周期计数).

根据cdecl r10和r11寄存器不保留,我希望在我的函数中使用它们作为临时变量,最好不要保留.它是否会导致任何编译器出现任何无法解决的问题/错误(到目前为止还没有遇到任何问题,但这是一个问题)?

assembly x86-64 abi cpu-registers calling-convention

6
推荐指数
2
解决办法
645
查看次数