Tag: 调用约定

从Assembly调用C函数(printf)时的Segfault

我在linux上使用NASM编写一个基本的汇编程序,它从C库(printf)调用一个函数。 不幸的是,我这样做会导致分段错误。 注释掉对printf的调用允许程序无错误地运行。 ; Build using these commands: ; nasm -f elf64 -g -F stabs .asm ; gcc .o -o ; SECTION .bss ; Section containing uninitialized data SECTION .data ; Section containing initialized data text db “hello world”,10 ; SECTION .text ; Section containing code global main extern printf ;————- ;MAIN PROGRAM BEGINS HERE […]

调用C函数,该函数不带参数参数

关于C调用约定和64/32位编译之间可能存在未定义的行为,我有一些奇怪的问题。 首先是我的代码: int f() { return 0; } int main() { int x = 42; return f(x); } 正如你所看到的,我用参数调用f,而f不带参数。 我的第一个问题是这个论点在调用时是否真的给了f。 神秘的线条 经过一点点objdump我得到了好奇的结果。 传递x作为f的参数: 00000000004004b6 : 4004b6: 55 push %rbp 4004b7: 48 89 e5 mov %rsp,%rbp 4004ba: b8 00 00 00 00 mov $0x0,%eax 4004bf: 5d pop %rbp 4004c0: c3 retq 00000000004004c1 : 4004c1: 55 push […]

__cdecl导致比__stdcall更大的可执行文件?

我找到了这个: 由于堆栈由被调用函数清理,因此__stdcall调用约定创建比__cdecl 更小的可执行文件,其中必须为每个函数调用生成堆栈清理的代码 。 假设我有两个function: void __cdecl func1(int x) { //do some stuff using x } void __stdcall func2(int x, int y) { //do some stuff using x, y } 在这里main() : int main() { func1(5); func2(5, 6); } IMO, main()负责清理对func1(5)的调用堆栈,而func2将清理func2(5,6)调用的堆栈,对吗? 四个问题: 1.为了调用main() func1 , main()负责清理堆栈,编译器在调用func之前和之后会插入一些代码(代码来清理堆栈)吗? 像这样: int main() { before_call_to_cdecl_func(); //compiler generated code for […]

为什么我可以通过带有太多参数的指针调用函数?

说我有这个function: int func2() { printf(“func2\n”); return 0; } 现在我声明一个指针: int (*fp)(double); 这应该指向一个带有double参数并返回int的函数。 func2没有任何参数,但是当我写的时候: fp = func2; fp(2); ( 2只是一个任意数字),func2`被正确调用。 这是为什么? 我为函数指针声明的参数数量没有意义吗?

x86调用约定:堆栈传递的参数应该是只读的吗?

似乎最先进的编译器将堆栈传递的参数视为只读。 请注意,在x86调用约定中,调用者将参数压入堆栈,并且被调用者使用堆栈中的参数。 例如,以下C代码: extern int goo(int *x); int foo(int x, int y) { goo(&x); return x; } 由OS X 10.10中的clang -O3 -c gc -S -m32编译成: .section __TEXT,__text,regular,pure_instructions .macosx_version_min 10, 10 .globl _foo .align 4, 0x90 _foo: ## @foo ## BB#0: pushl %ebp movl %esp, %ebp subl $8, %esp movl 8(%ebp), %eax movl %eax, -4(%ebp) leal […]

论证传递如何运作?

我想知道如何将参数传递给C中的函数。 存储的值在哪里以及如何检索它们? 可变参数传递如何工作? 此外,因为它是相关的:返回值怎么样? 我对CPU寄存器和汇编器有基本的了解,但还不足以让我彻底了解GCC向我吐出的ASM。 一些简单的带注释的例子将非常受欢迎。

如何将指向成员函数的指针传递给C函数?

可能重复: 使用C ++类成员函数作为C回调函数 我正在使用C库(winpcap)编写面向对象的库。 我需要传递当网络数据包作为函数指针到达时调用的回调函数。 我想将一个成员函数指针传递给winpcap,以保持我的设计对象的方向,并允许不同的对象接收不同的数据包。 但是据我所知,成员函数具有不同的调用约定,因此不能传递给C函数。 有没有办法来解决这个问题。 我使用boost :: bind进行的实验(除了试验和错误之外我几乎无法使用)并不富有成效。 有没有办法改变成员函数的调用约定? 这是我现在使用的回调函数的定义以及它实际传递给winpcap的定义 void pcapCallback( byte* param, const struct pcap_pkthdr* header, const byte* pkt_data ); pcap_loop( adhandle, 0, pcapCallback, NULL ); pcap_loop只接受函数的名称(目前在全局范围内)。 这是函数指针参数的定义( pcap_loop的第3个参数)。 由于这是第三方代码,我无法真正改变这一点。 我必须有一个可以采用这种forms的成员函数: typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, const u_char *); 据我所知,成员函数将使用thiscall,而c函数指针需要一个cdecl

调用一个函数指针,其指定函数的参数少于指针类型

请考虑以下代码: #include typedef int (*test_func_t) (int, int, int); int print_integer (int a) { std::cout << "num: " << a << "\n"; return a; } int main (int argc, char * argv[]) { test_func_t func = (test_func_t) &print_integer; std::cout << "calling with 3 parameters func(5,7,9)\n"; func(5,7,9); return 0; } 如您所见,类型(test_func_t)被定义为具有3个int参数的函数。 函数指针(func)被赋予一个指向“print_integer”的指针,该指针只接收一个参数,然后用3个参数(5,7,9)调用函数指针。 此代码工作并生成“num:5”输出。 gdb disas输出(Intel语法) disas main […]

从汇编调用交流function需要“asmlinkage”吗?

我正在编写一个将从汇编代码调用的C函数。 (具体来说,我想在linux内核的系统调用处理路径中做一些检查工作,所以我将在entry_32.S中调度系统调用之前调用c函数) 在定义我的c函数时,我对“asmlinkage”修饰符感到困惑。 我知道asmlinkage是告诉编译器参数将通过堆栈传递。 #define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0))) 问题: (1)在定义将从汇编代码调用的函数时是否需要asmlinkage? (2)gcc中的默认调用约定是什么。 如果我在定义交流function时省略“asmlinkage”,它是否意味着_cdecl或fastcall? (3)如果默认调用约定是cdecl,为什么需要asmlinkage,考虑到cdecl等于asmlinkage修饰符? (我在这里纠正吗?) (4)为什么那些系统调用函数都用asmlinkage声明。 我们可以先将参数复制到寄存器,然后调用那些系统调用函数吗? 从我的角度来看,在x86中,当发出系统调用时,参数很容易保存在寄存器中; 那么为什么还要在堆栈中保存然后通过堆栈约定强制执行这样的传递参数呢? 最后,任何人都可以推荐一些我可以参考混合汇编/ c编程的资源/书籍吗?

C:通过堆栈/寄存器问题返回值

我是C的新手,有一点我无法理解。 当函数返回不大于寄存器的东西时 – 我的编译器将它放在EAX中。 当我返回大结构(不是指针而是结构本身)时 – 它通过堆栈返回。 我的问题是:编译器如何知道如何调用另一个对象导出的函数? 有一个调用约定(比如stdcall)但它是关于传递参数,而不是读取返回的值,对吗? 应该有一些规则,如“如果声明的返回值大于EAX,则从[bp -…]”获取。 还有一个:是否正确地说我想要返回的对象,比寄存器大,应该存储在堆中并由指针返回以防止所有堆栈操作? 谢谢。