标签: calling-convention

COM调用x64上的约定

我试图得到关于COM在x64机器上的行为方式的明确答案.在调度x64机器上的COM接口时,Windows是否使用普通的x64调用约定(假设COM实现是64位)?具体来说,我动态生成我的vtbl条目以指向在运行时动态加载的一大块程序集.这个程序集需要知道如何从调用它的人那里正确地获取参数.因此,我想知道COM是否使用标准x64调用约定(非常快速调用)设置对程序集的调用.

com 64-bit assembly calling-convention

7
推荐指数
1
解决办法
1274
查看次数

7
推荐指数
1
解决办法
1392
查看次数

MSVC和mingw之间的接口二进制兼容吗?

我正在开发一个库,允许其用户(驻留在同一进程中的其他库)交换数据缓冲区和流.该库必须可以从MSVC和mingw代码中使用(更多兼容性不会受到影响,但并非严格必要).为了实现这一点,核心功能应该从一个小的,与编译器兼容的接口提供,以后可以通过使用客户端代码编译的便利层来隐藏.

该库的一个具有挑战性的方面是它必须是可扩展的,以便客户端可以提供自己的缓冲区和流实现,但核心库接口必须在发布后保持稳定.如果您对进一步的背景感兴趣,可以在论坛帖子讨论中阅读.

我试图了解编译器之间二进制兼容性的问题,但由于我是这个主题的新手,我会对我的结果发表评论.我在这里的标准定义的行为(结构可能会失败那个测试),只能在MinGW和MSVC之间的相容性不感兴趣,也许其他的编译器,如果方便可行的.

特别是结构是否兼容?它们统一由函数指针组成,因此我认为填充不会成为问题.另外,这里需要stdcall约定,还是cdecl也能正常工作?我可以不指定它,因为两个编译器都默认为cdecl吗?我是不是该?这就是我现在所拥有的:

#include <stdint.h>

typedef struct {
        uint32_t (__stdcall *read)(void*, uint8_t*, uint32_t);
        void (__stdcall *write)(void*, const uint8_t*, uint32_t);
        uint32_t (__stdcall *getBytesLeft)(void*);
        uint8_t (__stdcall *destroy)(void*);
} SharedStreamInterface;

typedef struct {
        uint32_t (__stdcall *read)(void*, uint8_t*, uint32_t);
        void (__stdcall *write)(void*, const uint8_t*, uint32_t);
        uint32_t (__stdcall *getBytesLeft)(void*);
        uint8_t (__stdcall *destroy)(void*);

        uint32_t (__stdcall *getreadpos)(void*);
        uint32_t (__stdcall *getwritepos)(void*);
        uint32_t (__stdcall *getlength)(void*);
        void (__stdcall *setreadpos)(void*, uint32_t);
        void (__stdcall *setwritepos)(void*, uint32_t);
        void (__stdcall *setlength)(void*, uint32_t);
} SharedBufferInterface;

extern "C" {
        // Functions …
Run Code Online (Sandbox Code Playgroud)

compiler-construction mingw calling-convention binary-compatibility visual-c++

7
推荐指数
1
解决办法
996
查看次数

__cdecl和__declspec调用约定混淆

我正在为第三方应用程序编写DLL.主要的软件工程师提到应用程序使用__cdecl(/ Gd)调用约定.我需要确保使用它.

另外,第三方提供了一个C++ DLL骨架,它导出如下函数:

#ifdef _EXPORTING
  #define DECLSPEC    __declspec(dllexport)
#else
   #define DECLSPEC    __declspec(dllimport)
#endif

#ifdef __cplusplus
   extern "C" {  
#endif

DECLSPEC int ICD_Create(char* id);
....
....
Run Code Online (Sandbox Code Playgroud)

我有点困惑.为什么使用__declspec约定而不是__cdedl导出函数?__declspec支持_cdecl吗?

谢谢.

c c++ dllimport calling-convention

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

C和C++调用约定有什么区别?

据我所知,调用约定依赖于编译器和体系结构.但C和C++调用约定之间是否存在明显差异?

c c++ compiler-construction linker calling-convention

7
推荐指数
2
解决办法
3324
查看次数

函数参数传入Linux内核中断处理程序(从asm到C)

当我阅读Linux内核源码时,我遇到了这段代码:

__visible void __irq_entry smp_apic_timer_interrupt(struct pt_regs *regs)   
{
    struct pt_regs *old_regs = set_irq_regs(regs);

    entering_ack_irq();
    local_apic_timer_interrupt();
    exiting_irq();

    set_irq_regs(old_regs);
}
Run Code Online (Sandbox Code Playgroud)

该函数smp_apic_timer_interrupt()有一个参数.调用此函数是通过一段汇编语言代码:

ENTRY(apic_timer_interrupt)
     RING0_INT_FRAME;     
     ASM_CLAC;           
     pushl_cfi $~(0xef);
     SAVE_ALL;         
     TRACE_IRQS_OFF
     movl %esp,%eax;
     call smp_apic_timer_interrupt; // <------call high level C function       
     jmp ret_from_intr;      
     CFI_ENDPROC;           
ENDPROC(apic_timer_interrupt)
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚高级C函数如何smp_apic_timer_interrupt()获取其参数(通过哪个寄存器)?

x86 assembly calling-convention linux-kernel interrupt-handling

7
推荐指数
2
解决办法
1225
查看次数

为什么gcc在按值传递普通结构时会发出不需要的内存访问?

众所周知,一些没有非平凡复制的小结构,没有非平凡的dtor在寄存器中传递.

引用ARM程序调用标准:

大于32位的基本类型可以作为参数传递给函数调用,或者作为函数调用的结果返回.当这些类型在核心寄存器中时,以下规则适用:双字大小类型在两个连续寄存器中传递(例如,r0和r1,或r2和r3).寄存器的内容就好像该值是通过单个LDM指令从存储器表示加载的.

事实上,我可以轻松地用铿锵声证实这一点.然而,gcc为这样一个简单的代码片段发出了大量的内存加载和存储:

struct Trivial {
    int i1;
    int i2;
};

int foo(Trivial t)
{
    return t.i1 + t.i2;
}
Run Code Online (Sandbox Code Playgroud)
$ clang++ arm.cpp -O2 -mabi=aapcs -c -S && cat arm.s

add r0, r0, r1
bx  lr
Run Code Online (Sandbox Code Playgroud)
$ g++ arm.cpp -O2 -mabi=aapcs -c -S && cat arm.s

sub     sp, sp, #8
add     r3, sp, #8
stmdb   r3, {r0, r1}
ldmia   sp, {r0, r3}
add     r0, r0, r3
add     sp, sp, #8
bx      lr
Run Code Online (Sandbox Code Playgroud)

我正在使用由ArchlinuxARM发行版提供的gcc和clang,在raspberry pi 2(gcc 5.2)上运行,但我也用基于gcc的交叉编译器再现它.

c++ assembly arm calling-convention

7
推荐指数
1
解决办法
137
查看次数

在64位.NET应用程序中是否忽略了CallingConvention?

当通过P/Invoke通过显式64位.NET应用程序与64位本机库交互时,属性中的CallingConvention属性是否DllImport被有效忽略?

我问这个是因为在"传统"x86上你必须指定调用者或被调用者清理堆栈变量的方式(以及函数本身如何使用某些CPU寄存器等); 但据我了解,x64只有一个约定__fastcall(__vectorcall尽管最近添加了).

那么__fastcall,无论你为CallingConvention属性设置什么,CLR都会继续使用x64约定来编组函数调用?

.net c# pinvoke calling-convention

7
推荐指数
1
解决办法
417
查看次数

每个PUSH指令是否在x64上推送8个字节的倍数?

在x64上,每个PUSH指令是否会推送8个字节的倍数?如果没有,它会推动多少?

此外,每个函数参数消耗多少堆栈空间?

assembly x86-64 calling-convention

7
推荐指数
2
解决办法
3104
查看次数

为什么在 System V AMD64 ABI 中不使用 RAX 来传递参数?

我不明白不在 RAX 中传递参数有什么好处,因为返回值在 RAX 中,无论如何它都会被被调用者破坏。

有人可以解释一下吗?

x86-64 calling-convention

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