在windows上,常用的函数调用方式有:
Pascal方式,WINAPI(_stdcall)方式 和C方式(_cdecl)
_cdecl调用规则:
1,参数从右到左入堆栈
2,在函数返回后,调用者要负责清除堆栈
所以这种调用常会生成较大的可执行文件。
_stdcall又称为WINAPI调用方式,规则:
1,参数从右向左入堆栈
2,被调用的函数在返回前自行清理堆栈
所以这种调用会生成比cdecl小的代码
Pascal调用方式,主要用在WIN16函数库中,现在基本不用
规则:
1,参数从左向右入堆栈
2,被调用函数在返回前自行清理堆栈
此外,在Windows内核中还常见的有快速调用方式(_fastcall)
在C++编译的代码中有this call方式(_thiscall)
在windows中,不管哪种方式,返回值都写在eax中,外部从中获取返回值
_cdecl方式步骤
1,保存ebp
2,保存esp到ebp
3,在堆栈中腾出一个区域来保存局部变量
4,保存ebx,esi,edi到堆栈中,函数调用完后返回
5,把局部变量区域初始化为0xcccccccch,实际上是int 3指令机器码,这是一个断点软中断
6,做函数里应该做的事情
7,恢复ebx,esi,edi,esp,ebp,最后返回
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
for循环的汇编代码分析:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
从上面的汇编代码可以分析出,for循环就是cmp指令+jmp指令
根据cmp判断然后跳转到那个位置执行代码
do...while循环分析
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
从上面代码可以看出
本质do...while循环和for差不多
while循环:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
if...else if...else语句分析
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
|
switch...case 代码分析
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
|
结构体分析
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
|
从上面不难看出,结构体赋值是先经过计算,然后把基址存放的一个变量
然后计算每个结构体的偏移量,然后对每个struct进行定数累加赋值
枚举,联合,结构结合分析:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
|
我们发现这段代码和上面的汇编后代码基本一样,因此我们知道,汇编中对共用体和枚举类型没有特别的处理
并不会引入新的代码,因为共用体和枚举都是方便给程序员用的,本质没什么改变
高级C代码的汇编分析