-
-
[原创]汇编眼中的函数调用参数传递以及全局与局部变量与“基址”
-
发表于:
2020-2-4 21:14
3487
-
[原创]汇编眼中的函数调用参数传递以及全局与局部变量与“基址”
作为刚往底层方向走的一只菜鸟,今天为各位分享一篇名为汇编眼中的函数调用参数传递以及全局、局部变量与“基址”,好了,废话不多说,先来看看C语言代码:
本次的分享主要以画堆栈图为主,通过画图的方式来看看这段代码是如何运作的
我们先写一句汇编代码,mov eax,eax其实这句代码并没有什么用,也就是将eax的值移入eax中,这句代码对于我们的作用仅作为断点,我们F5运行下程序并且切换到反编译界面
右键之后点击Go To Disassemble,也就是进入反编译界面,我们来看看反编译的代码
这就是咱们main函数反编译后的结果,那么现在我们记录一下ebp,esp的值,并且画出现在的堆栈图
ESP = 0019FEF4
EBP = 0019FF40
黄色=ebp~esp初始的内存
那好,我们继续来看代码
这里是我们自己写的汇编代码,编译器也没有改动过可以说是本色出演,这里内存没有变化,好,那么我们接着来看add函数这里的调用
可以看到函数调用的时候首先是将3、1这两个值推入栈中,但是又有疑问了“add函数的调用是这样的add(1,3),为啥首先推入栈中的是3而不是1呢?”之所以这样是因为栈中是先进后出的,所以参数进入栈中的顺序是从右向左的,当然这里也可以看到函数中的参数是压入栈中然后取出来而不是通过通用寄存器eax,edx,ebx这些来传送参数的,其实这也好理解,因为通用寄存器只有八个,像esp,eip,ebp这样的寄存器还不能随便改,能用的也只有剩下的几个,参数超过剩下的几个咋办?那就只能用堆栈了。我们继续来看F10单步执行一下,看看堆栈的变化
我们再看看EBP和ESP
这里可以看到压入一个3后栈顶指针减去了4h,至于为啥减去4h呢?是因为一个int类型的数据宽度是4Byte=32Bit,能存入的最大数也就是0xFFFFFFFF,16进制数又是2进制数的简写形式,一个二进制数需要4Bit来存储,所以4位二进制数最大的值为1111转换为16进制后刚好为F,这样也方便了开发者,存储空间中我们看到的数据都是16进制数
十六进制 二进制
0h 0b
1h 1b
2h 10b
3h 11b
4h 100b
5h 101b
6h 110b
7h 111b
8h 1000b
9h 1001b
Ah 1010b
Bh 1011b
Ch 1100b
Dh 1101b
Eh 1110b
Fh 1111b
可能以上讲得有些出入,如有错误,请帮忙纠正,好了,我们接着来看,接下来push 1进去,我们来看看现在的堆栈图:
继续看下面的代码:
接着是call,call指令在汇编中多用于函数调用,call指令做了两个操作,
1、Push 00401103(下一行代码地址)
2、Jmp 0040100A(函数地址)
这里我们F11一下,遇到call指令后按F11进入函数即可,这样我们就可以看到函数体中的指令
这里CALL之后看看堆栈中的变化:
继续向下走,F11后跳转到的结果如下
这里是编译器决定的,不是所有编译器call后会进入一个jmp指令中转,再F11一下
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)