3 汇编的函数调用
3.1 无参数和返回值的函数调用
void func_void() { printf("func, no param, no return value\n"); }
// func_void(); asm ("call func_void"); // call指令调用函数,该函数为C命名风格,C++编译则需使用C++名称。
3.2 调用函数并获取返回值
int func_get_value () { int a = 11; int b = 12; return a + b; }
int a ; // a = func_get_value();
asm ( "call func_get_value\n\t" "mov %%eax, %0\n\t" // 按照调用约定,EAX/RAX寄存器存放返回值。 : "=m" (a) ); printf("%d\n", a); // output: 23
3.3 调用参数数目在6个以内的函数
- 根据System V X86_64调用约定,6个以内(含)的参数,放入寄存器。
int func_add(int a, int b) { return a + b; }
int c = 0; // c = func_add(100 , 200); asm ( "mov $100, %%edi\n\t" // 根据调用约定,寄存器edi放入第一个参数 "mov $200, %%esi\n\t" // esi放入第二个参数 "call func_add\n\t" "mov %%eax, %0\n\t" : "=m" (c) ); printf("%d\n", c); // output: 300
3.4 调用参数数目在6个以上的函数
- 根据System V X86_64调用约定,6个以内(含)的参数,放入寄存器,第7个参数以上则写入栈。
int func_add8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) { return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8; }
void test_add8() { int s = 0; // s = func_add8(1, 2, 3, 4, 5, 6, 7, 8); asm ( "mov $1, %%edi\n\t" // 按调用约定先将前6个参数写入对应的寄存器 "mov $2, %%esi\n\t" "mov $3, %%edx\n\t" "mov $4, %%ecx\n\t" "mov $5, %%r8d\n\t" "mov $6, %%r9d\n\t" "pushq $8\n\t" // 后2个参数逆序压栈,压栈后栈顶指针rsp会上移 "pushq $7\n\t" "call func_add8\n\t" // 调用函数 "addq $16, %%rsp\n\t" // 栈顶指针复位,回复到之前上移前的位置。 "mov %%eax, %0\n\t" : "=m" (s) ); printf("s = %d\n", s); // output: 36