赞
踩
这个实例运行在VS2008当中,旨在帮助我们熟悉VS2008当中的调试,反汇编等基本操作。并帮助理解汇编语言。
基本调试方法
Debug or Release
F10:单步执行,不进入函数
F11:单步执行,要进入函数
F5:启动调试
断点:程序某一行可以设上断点,程序调试经过该处将会停下来。此时可以查看变量、内存、寄存器等值
F9
#include "stdafx.h"
int gi;
int _tmain(int argc, _TCHAR* argv[])
{
gi = 12;
return 0;
}
反汇编查看汇编代码
Ctrl+Alt+d(不一定,Alt+8)
调试→窗口→反汇编(注意,只有在点击调试之后才会有这样的选项出现)
10: gi = 12;
0041138E mov dword ptr ds:[00417140h], 0Ch
在反汇编窗口中,解释右键弹出的各个选项
0041138E mov dword ptr ds:[00417140h], 0Ch
前面0041138E代表指令存放地址
后面的 mov dword ptr ds:[00417140h], 0Ch 是汇编指令
我们可以看到0Ch就是源操作数12 目的地址是 dword ptr ds:[00417140h]
当我们在反汇编代码窗体当中点击右键,然后可以选择在反汇编结果中我们需要显示的内容,如果我们选上显示符号名,那么dword ptr [gi (417140h)],0Ch 就会出现gi变量名,而事实上在汇编指令中是不会出现变量名的,这样只是让我们容易理解罢了。
当我们选上显示代码字节的时候,我们的反汇编结果会
0041138E C7 05 40 71 41 00 0C 00 00 00 mov dword ptr [gi (417140h)],12345678h
在指令存放地址与汇编指令之间出现了C7 05 40 71 41 00 0C 00 00 00 就是mov指令的机器码。
C7 05 (代表MOV指令)40 71 41 00(地址00417140H) 0C 00 00 00(代表值12)
问题一: 00417140h是gi的地址吗?
问题二: Mov指令真的放在0041138Eh吗?
怎么实证?
#include "stdafx.h"
int gi;
int _tmain(int argc, _TCHAR* argv[])
{
gi = 0x12345678;
printf("%x",&gi);
getchar();
return 0;
}
printf("%x\n", &gi);
太麻烦了!
调试à窗口→监视à→监视1
输入&gi (选择一个空行,单击名称列)
我们继续分析mov指令的机器码:套用前面对地址的分析,第三块从右往左看就是0000000C 就是12,而int类型在32位机上就是4字节,所以这条指令中用了4字节表示了12。
这样我们似乎发现了一个规律,计算机上表示的整数在内存中是按照字节倒序存储的。0000000C在内存当中就是0C 00 00 00 00417140就是40 71 41 00
我们可以进行验证,将gi = 12 改成gi = 0x12345678
我们再次在gi = 0x12345678 的位置打断点调试,再次反汇编查看mov指令的机器码
0041138E C7 05 40 71 41 00 78 56 34 12 mov dword ptr [gi (417140h)],12345678h
78 56 34 12 确实如我们所料,就是如此
这里引出整数在计算机上的表示方式的知识。在内存中如何存储整数只是一种规范,分为大端机和小端机。
小端机:整数逻辑上的最低字节放在内存的最低地址,次低字节放在内存的次低地址,依次存放。比如,0x12345678放到内存中就是78563412.Intel的X86系列CPU姐姐就是小端机
大端机:与小端机正好相反。0x12345678放到内存中就是12345678 。
PowerPC SUN的SPARC Motorola 6800 就是大端机
现在我们想要查看mov指令执行的效果,要看赋值效果,我们需要用另一个调试利器---------内存观察窗体。在VC2008中选择调试→窗口→内存→内存1 之后我们就可以看到会出现一个内存查看窗口,我们输入我们要查看的gi的地址
00417140 之后看到
上面的图表明了从0x00417140 地址开始的12个字节的内存内容,
看的出来0x00417140 的四个字节代表的是0值
我们按下F11键之后,进入单步调试,执行当前函数,跳到下一语句
其实F10 也能完成相关功能
二者都是调试,两个在普通的语句上没有什么区别,都是执行下一行语句,但如果当前行是一个函数调用时,就不一样了。
F10的效果是执行下一条语句
F11的效果是进入这个调用函数的内部,执行函数内部的下一行语句
gi所在的内存00417140变成了78563412 这是赋值之后产生的结果变化。
PS:在调试这一步的时候 虽说 gi = 0x12345678 调试到这一步,但是这个语句事实上并没有执行的。
至此我们分析了mov指令的结构,整数在内存中的存放,以及验证了了gi的存放地址是00417140H
现在来看之前提出的问题,mov在0041138Eh吗?
怎么来设计这个实验呢?既然指令依然存放在内存当中,本质也是内存中的一些数据,那么我们是否可以通过内存窗体来观察呢?对于gi = 0x12345678;
该汇编指令存放地址(假定的0041138Eh)的值是mov指令的机器码
C7 05 40 71 41 00 78 56 34 12
我们再内存窗体地址栏当中中输入 0041138Eh,回车,结果发现存放的就是该mov指令的机器码
确实该内存段落内存放的是mov指令的机器码。
下面我们再做一个实验,通过改变内存窗体中的内存的值,来改变gi的值,
我们要将其改成987654
我们通过widows自带的程序员计算器来计算出其对应的十六进制值
000F1206
由于是小端机存放我们注意顺序
我们将内存窗体改成
看的出来,我改错了,改成了f1200600了
F11单步调试之后,我们再监视窗体当中查看gi的值,
在监视窗体中使用十六进制查看结果:因为调试器用十六进制数显示指针变量值。我们只需要骗骗它,将被查看的变量强制转换成void * 我们输入(void *)gi之后就会发现
确实是0xf1200600了
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。