究竟C中的函数调用时怎么回事呢?我们很像知道,因此做了下面的实验。
这一次比之前的弄得明白一点了,希望不会误导大家!
#include <stdio.h>
void ff(char* s) {printf("%s", s);}
void main(void){
void fff(char* s) {printf("%s", s);}
ff("Hello, C language!\n");
fff("Hello, World!\n");
char* s0 = "This is C language!\n";
char* s1 = "This is C language too!\n";
char* s2 = "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n";
asm("movl %%eax, (%%esp)\n""call _printf"::"a"(s2));
asm("movl %%eax, (%%esp);""call _ff"::"a"(s0));
asm("movl %%eax, (%%esp);""call *%%ebx"::"a"(s1),"b"(fff));
asm("movl %%eax, (%%esp)\n""call _printf"::"a"(s2));
asm("movl %%eax, (%%esp);""call _ff"::"a"(s0));
asm("movl %%eax, (%%esp);""call *%%ebx"::"a"(s1),"b"(fff));
asm("movl %%eax, (%%esp)\n""call _printf"::"a"(s2));
asm("movl %%eax, (%%esp);""call _ff"::"a"(s0));
asm("movl %%eax, (%%esp);""call *%%ebx"::"a"(s1),"b"(fff));
asm("movl %%eax, (%%esp)\n""call _printf"::"a"(s2));
asm("movl %%eax, (%%esp);""call _ff"::"a"(s0));
asm("movl %%eax, (%%esp);""call *%%ebx"::"a"(s1),"b"(fff));
}
至于代码中为什么不用压栈指令,而是用数据传送指令使参数入栈,我就明白了,只是机械地参考了反汇编后的代码。
#include <stdio.h>
void ff(char* s) {}
void f(void){
void fff(char* s) {}
ff("Hello, World!\n");
fff("Hello, World!\n");
}
/*
test506.o: file format pe-i386
Disassembly of section .text:
00000000 <_ff>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 90 nop
4: 5d pop %ebp
5: c3 ret
00000006 <_fff.1887>:
6: 55 push %ebp
7: 89 e5 mov %esp,%ebp
9: 83 ec 04 sub $0x4,%esp
c: 89 4d fc mov %ecx,-0x4(%ebp)
f: 90 nop
10: c9 leave
11: c3 ret
00000012 <_f>:
12: 55 push %ebp
13: 89 e5 mov %esp,%ebp
15: 83 ec 14 sub $0x14,%esp
18: 8d 45 08 lea 0x8(%ebp),%eax
1b: 89 45 fc mov %eax,-0x4(%ebp)
1e: c7 04 24 00 00 00 00 movl $0x0,(%esp)
25: e8 d6 ff ff ff call 0 <_ff>
2a: 8d 45 fc lea -0x4(%ebp),%eax
2d: c7 04 24 00 00 00 00 movl $0x0,(%esp)
34: 89 c1 mov %eax,%ecx
36: e8 cb ff ff ff call 6 <_fff.1887>
3b: 90 nop
3c: c9 leave
3d: c3 ret
3e: 90 nop
3f: 90 nop
*/
下面是之前的,谨慎参考,代码有误。
这里"addl $(4 * 1), %esp"似乎是多余的,但我不确定。不过用jmp就不能成功返回到汇编下面的语句继续执行。也许是要在前面加入"pushl _retaddr"之类的语句把,不过这里可能要在紧邻的下面加入retaddr:之类的标号,才能正确的返回吧。留在明天再尝试吧,也好凑个篇幅。
#include <stdio.h>
//这里对函数或是变量都不能定义为局部的,即不能再main内部定义
//否则程序因未定义变量而不能连接
void f(int a){
printf("0x%x\n", a);
}
int a = 100;
const char* str = "Hello, world!\t%d\t\n";
int main(void){
printf("0x%x\n", f);
asm("pushl $256;"
"call _f;"
"addl $(4 * 1), %esp");
asm("pushl $15;"
"call 0x401460;"
"addl $(4 * 1), %esp");
asm("pushl _a\n"
"pushl _str\n"
"call _printf\n"
"addl $(8 * 1), %esp");
}