【3.A.S.T】网络安全爱好者's Archiver

黑客学习

柔肠寸断 发表于 2009-5-19 23:57

汇编基础一日一学习5

汇编基础一日一学习5
[b]   [color=red]大家好,今天我给大家讲解的是栈,今天这节课程也非常重要。 这对你以后调试程序是非常有帮助的。因为我们程序中的局部变量以及一些函数的参数都是栈中分配内存的。栈也是由我们编译器自动分配释放的。     

    那么栈到底是什么呢? 栈是一种具有特殊的访问方式的存储空间。它的特殊就是在于最后进入这个空间的数据,最先出去。

    举个例子,假如这时我们有3个动物。 猫咪、猴子、兔子。 那么我们按先后的顺序我们先把猫咪放进栈中,然后再把猴子放到栈中,最后把兔子放到栈中。那么此时,大家可以看到。兔子现在存在栈顶。那么此时我们取出的就是兔子了。而最先放进去的时猫咪,它则最后取出。这就是栈的“后进先出”的特性。自己如果不理解,在家里拿个茶缸,然后找几个物品,按先后顺序把物品放进去,然后在取出来。自己来理解下“后进先出”这个特性。[/color][/b][img]http://www.hacker.com.cn/upload/forum/200804/20080411190806R.jpg[/img]


[b][color=black]我们目前的cpu都有栈的设计。例如80386cpu等。。。。 这些cpu也提供了相应的指令来以栈的方式访问内存空间。这也表示我们编译的程序被映射到内存以后有一段栈空间供我们访问。

问题来了?我们怎么才能知道我们栈空间在那里呢。
呵呵还记得之前讲解的eip寄存器吗。 我们pe loader将我们的程序映射到内存空间以后,将程序的入口点赋值给我们的eip寄存器。这样cpu读取eip寄存器的值就可以将我们入口点的汇编指令读取并运行了。。 那么从这里就可以下结论,我们栈区的内存地址,肯定也有相应的寄存器存储。

没错,这个寄存器就是esp寄存器。程序第一次被PE loader映射到内存,那么Pe loader会把栈区的内存偏移地址赋值给esp寄存器。

这里我们栈区的地址也知道如何访问了。。 那么像栈这么有个性的内存空间,肯定也有个性的指令来访问并存取数据吧。没错,栈提供了两个“存”“取”的指令,“push” 和 “pop”。
这两个指令一个“存”一个是“取”。也可以说一个是“入”一个是“进”。  这里我用“存”和“取”来表示,大家会更好的理解些。。 比如push eax 就是将eax寄存器的值存入栈中。。
pop eax 就是将eax取出堆栈。

但是这里注意了。刚刚我已经说了,esp寄存器是存放栈区的内存地址的。但是如果一旦我们通过push 将一段数据存入堆栈,那么如果esp不会自动增加或减少大小。那么它就over了。下次存入的时候就会将之前的数据给覆盖。还好,聪明的Intel公司,已经想到了这一点。
但是不要慌张,我们存入数据我们的esp寄存器应该相应的增加对吧?
但是我们程序被映射到内存以后,相应的是高地址的数据存入高地址,低地址的数据存入低地址。不明白吗?去看看上节课。或者拿C32asm打开一个文件。文件最底部的数据映射到内存以后也是在地址最高处的。[/color] [/b][b][color=limegreen]所以压入堆栈,我们的数据增加,相应的偏移却是减少。[/color][/b]


[b][color=red]每次我们通过push 存入数据它esp寄存器的值就会相应的禁烧我们存入数据的字节大小。举个例子
例如此时 eax = 00402500h  esp寄存器= 00200000h
执行 push eax的时候esp也相应的减少   
此时 esp = (00200000 – 4)h   

此时我们如果想取数据的话。
pop eax 就可以将esp寄存器中的偏移地址的数据取出并存放到 eax寄存器中。
数据取出来了,相应的数据减小。但是我们的偏移却增加了。因为我们每次存取栈都要通过esp寄存器才能知道栈的位置,所以我们这里可以把esp归结为esp永远是指向栈顶的。
数据取出来,此时我们栈没了数据相应的地址也向下降了相应数据字节的大小。 但是我们的内存是越深处地址越高。所以此时我们的地址是增加了。
所以pop eax寄存器执行后  esp = (00200000 -4 +4)

不知道大家是否明白了?如果不懂的话多读几次。

因为今天这节课程比较多,如果全部讲的话怕大家接受不了。 接下来我给大家写一个实例。
来详细的讲解下。

如果我们将0040000h – 00400020h , 初始状态栈是空的,那么此时esp指向的地址是多少?

切记:记得一定要把上节课的内容也要嵌入进来。。怕大家不能理解。esp永远指向我们栈顶元素。栈而且它最初指向的就是栈顶,也就是我们栈空间的最顶部。记住内存越深,地址也就越高。哈哈

正确答案:esp = 00400021h 。

所以esp指向的地址,必须够我们写入4个字节的数据(因为80386的数据线一次只能传送4个字节的数据)。并且写入后不能发生越界行为。

怕大家不能消化,今天就讲这么多吧。。。。。接下来来用几个小作业。来巩固下知识。


小作业:
(1)        假如此时eax = 00402500h , esp = 00400000h。那么执行Push eax 后, esp寄存器等于多少???
   
(2)        假如此时eax = 000001h , esp 00003020h。执行pop eax指令后, esp寄存器等于多少??

(3)   假如此时我们将 00300000h – 0030001Ah作为栈空间,初始状态栈是空的。此时esp等于多少???[/color][/b]










[img]http://www.hacker.com.cn/upload/forum/200804/200804112121277.gif[/img]

EndTo偌枫 发表于 2009-5-27 11:03

学习阿Y荡阿.em66.

plantseth 发表于 2009-5-29 19:28

1.00400000h-4
2.00003020h+4
3.0030001Ah+1

自在飞花 发表于 2009-6-2 23:17

不行了,读不下去了。已经学完四课了,先休息下。
原来用C32asm调试啊。等安完了再接着学习。
老师辛苦了。

自在飞花 发表于 2009-6-3 20:41

(1)        假如此时eax = 00402500h , esp = 00400000h。那么执行Push eax 后, esp寄存器等于多少???
   [color=Red]003FFFFCH[/color]
(2)        假如此时eax = 000001h , esp 00003020h。执行pop eax指令后, esp寄存器等于多少??
[color=Red]00003024H[/color]
(3)   假如此时我们将 00300000h – 0030001Ah作为栈空间,初始状态栈是空的。此时esp等于多少???
[color=Red]0030001BH[/color]

scien 发表于 2009-6-6 01:00

有点怪了

多看几遍!!!

caimingbing 发表于 2009-12-14 11:23

小柔,你好厉害啊!

hkhs615 发表于 2009-12-17 16:19

学习.................

页: [1]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.