Debug指令练习
2019-06-06 本文已影响0人
萍水间人
关于之前的一部分指令,可以参考这篇文章
rep stosd循环:
从lea edi , [EBP+arg_0] 开始,到rep stosd 结束。EDI中存入的是循环操作的起始地址,ECX存入的是循环次数,EAX是循环填入的值。这一段的操作就是从EBP+var_40处开始,循环十次,向下依次填入CCCCCCCC,写入的长度由EAX决定,32位。
1: #include <stdio.h>
2: #include <stdlib.h>
3:
4: int main(int argc, char *argv[])
5: {
00401010 push ebp
00401011 mov ebp,esp
00401013 sub esp,44h
00401016 push ebx
00401017 push esi
00401018 push edi
00401019 lea edi,[ebp-44h]
0040101C mov ecx,11h
00401021 mov eax,0CCCCCCCCh
00401026 rep stos dword ptr [edi]
;这部分之前的指令都是一些初始化的工作
6: float fFloat = (float)argc;
00401028 fild dword ptr [ebp+8]
0040102B fst dword ptr [ebp-4]
7: printf("%f", fFloat);
0040102E sub esp,8
00401031 fstp qword ptr [esp]
00401034 push offset string "%f" (00426020)
00401039 call printf (00401090)
0040103E add esp,0Ch
8: argc = (int)fFloat;
00401041 fld dword ptr [ebp-4]
00401044 call __ftol (004011f8)
00401049 mov dword ptr [ebp+8],eax
9: printf("%d", argc);
0040104C mov eax,dword ptr [ebp+8]
0040104F push eax
00401050 push offset string "%d" (0042601c)
00401055 call printf (00401090)
0040105A add esp,8
10: return 0;
0040105D xor eax,eax
11: }
现场开始单步调试
此时的内存和寄存器值:
0x0012FF84是esp当前的指向
当我们push一个ebp进去之后,esp减去4,指向了0x0012FF80
,往地址增大的方向数四个字节就是刚刚的ebp的值,这我就理解了按字节编址的机器中都是往地址高的地方去数四个字节
push两个值进去之后,
标注除了ebx和esi寄存器 继续push了edi寄存器的值
lea edi,[ebp-44h]是将esp-44h然后将这个地址赋值给edi,这个方括号有点让人迷
edi此时指向了这个地址
接下来要完成的操作是:
0040101C mov ecx,11h
00401021 mov eax,0CCCCCCCCh
00401026 rep stos dword ptr [edi]
连续17次rep stos
这样就大概解释清楚了吧
0x02float指令分析
6: float fFloat = (float)argc;
;将地址ebp+8处的整型数据转换成浮点型,并放入ST(0)中,对应变量argc
00401028 fild dword ptr [ebp+8]
;从ST(0)中取出数据以浮点编码方式放入地址ebp-4中,对应变量fFloat
0040102B fst dword ptr [ebp-4]
ctrl+f10让其执行到贯标所处的位置
[ebp+8]处对应的值:
这里是ebp-4对应的值,还没有被修改
此处的值被修改成了0x3F800000
而此时的float值也被修改了
这是对应的二进制
0表示符号位,011 1111 1表示指数部分,最后的全0代表尾数部分。
指数是加了127的,此处减去127即为0,又由于尾数中隐含前导1
所以0x3F800000
就是1对应的浮点数表示方法
略过printf函数
这是第一次打印出来的值
8: argc = (int)fFloat;
;将地址ebp-4处的数据以浮点型压入ST(0)中
00401041 fld dword ptr [ebp-4]
;调用__ftol函数进行浮点转换
00401044 call __ftol (004011f8)
;转换后的结果放入eax中,并传递到ebp+8地址处
00401049 mov dword ptr [ebp+8],eax
这是转换函数的实现
004011F8 push ebp
004011F9 mov ebp,esp
004011FB add esp,0F4h
004011FE wait
004011FF fnstcw word ptr [ebp-2]
00401202 wait
00401203 mov ax,word ptr [ebp-2]
00401207 or ah,0Ch
0040120A mov word ptr [ebp-4],ax
0040120E fldcw word ptr [ebp-4]
00401211 fistp qword ptr [ebp-0Ch]
00401214 fldcw word ptr [ebp-2]
00401217 mov eax,dword ptr [ebp-0Ch]
0040121A mov edx,dword ptr [ebp-8]
0040121D leave
此时eax中存放了返回的值
这里让我比较困惑了,ebp+8处存放的值就是之前的argc,所以在mov dword ptr [ebp+8],eax
时并没有修改此处的值