返回列表 发帖

[原创] 汇编基础专题一日一学习14

汇编基础专题一日一学习14
         
        今天我们来学习下call和ret指令,它们都是转移指令,也都修改eip寄存器。他们经常的被用来实现在自程序设计。一般我们调用子程序都是通过call来实现的。


那么一般我们的call指令格式是

   

    call   内存地址

    这个内存地址就是我们子程序的地址,我们程序执行完call 内存 指令后,相应的eip=内存地址。

    举例 call  00403020

    执行指令后 eip寄存器= 00403020 。我们都直到我们的cpu每次读取数据执行都是先读取我们eip寄存器,然后定位内存地址,最后在将内存中的数据传送到指令缓存区,最后执行,那么相应eip也就+读取数据的字节大小。

   但是转移指令是直接 eip = 转移的地址,例如我们之前学的jmp 和今天学的call 。

   
   call最重要的还有一点是,这里我举例说明

    假设此时call 00403020指令还没有执行。 假设此时cpu通过eip寄存器定位到了call 00403020指令上,此时读取指令到指令缓冲区(注意:此时并没有开始执行,转移指令的eip值是变化两次的),新eip值= 旧eip +指令字节大小,此时我们cpu会将新eip的值压入堆栈。等待我们子程序执行完后,用ret指令将其之前eip值返回,从而使程序继续运行。。 最后才开始执行call 00403020 ,然后设置eip = 00403020。


    那么重定位的技巧就是利用call的这个特性:

   
    call $4    ;$表示是当前的地址, $4就是当前的地址+4
    pop eax
    此时将我们的call 所在的内存地址+指令字节大小后值(也就是读取call $4到指令缓冲区后, eip的值)压入堆栈的数据,再通过pop eax 取出到eax寄存器中,然后计算重定位差。
   

   ret指令呢,

  就是将eip赋值为 eip = 此时esp指向堆栈中的数据(也就是之前压入堆栈中的地址)
   
  并且将esp+4  。
  也就是
  esp = esp +4




   有必要说下 一般我们程序的子程序的开头是,因为ebp是基址寄存器,并且是段地址是位于堆栈段的,所以我们高级语言都采用这样的形式来通过ebp做指针来进行间接的寻址。

   push ebp
   mov ebp, esp
   ;初始化

   最后通过leave指令来恢复esp 和ebp寄存器。
   
  ;这些我们现在还没讲,所以大家知道具体功能是什么就可以了。


小作业:

今天我们主要是深入的来了解下call 以及ret指令,那么今天的作业改为手工作业,这里我写了一个子程序的例子,大家回去用ollydbg来分析下,注意看下call 以及ret指令 执行后esp eip 等寄存器的变化。。最后把自己的分析报告写到帖子中。 (分析报告的内容主要是:call执行后esp的发生的变化,以及ret指令后发生的变化)
希望做站长本人的学生请点击
http://www.3ast.com/viewthread.php?tid=13841
QQ790653916只负责SEO以及收费教学等方面联系,他人勿扰

于智者同行,你会不同凡响;与高人为伍,你会登上巅峰

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

TOP

返回列表