一个全局变量的例子

来源:互联网 发布:莱州网络花店 编辑:程序博客网 时间:2024/05/22 14:02

这个实例运行在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)],0C 就会出现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

 

问题一: 00417140hgi的地址吗?

 

问题二: 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.IntelX86系列CPU姐姐就是小端机

   大端机:与小端机正好相反。0x12345678放到内存中就是12345678 

PowerPC   SUNSPARC  Motorola 6800 就是大端机

   

现在我们想要查看mov指令执行的效果,要看赋值效果,我们需要用另一个调试利器---------内存观察窗体。在VC2008中选择调试→窗口→内存→内存之后我们就可以看到会出现一个内存查看窗口,我们输入我们要查看的gi的地址

00417140  之后看到

 

上面的图表明了从0x00417140  地址开始的12个字节的内存内容,

看的出来0x00417140  的四个字节代表的是0

我们按下F11键之后,进入单步调试,执行当前函数,跳到下一语句

其实F10 也能完成相关功能

二者都是调试,两个在普通的语句上没有什么区别,都是执行下一行语句,但如果当前行是一个函数调用时,就不一样了。
F10的效果是执行下一条语句
F11的效果是进入这个调用函数的内部,执行函数内部的下一行语句

 

gi所在的内存00417140变成了78563412  这是赋值之后产生的结果变化。

 

PS:在调试这一步的时候 虽说 gi = 0x12345678 调试到这一步,但是这个语句事实上并没有执行的。

 

至此我们分析了mov指令的结构,整数在内存中的存放,以及验证了了gi的存放地址是00417140H  

 

现在来看之前提出的问题,mov0041138Eh吗?

怎么来设计这个实验呢?既然指令依然存放在内存当中,本质也是内存中的一些数据,那么我们是否可以通过内存窗体来观察呢?对于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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

原创粉丝点击