zoukankan      html  css  js  c++  java
  • 汇编invoke和call的关系

    win32汇编里面,我们既可以用invoke也可以用call调用子程序/函数,不过invoke使用简单方便,所以绝大多数情况我们都用invoke。
    但是很多人只是知道使用它,对它却不是很了解。我以前对这个问题也是一直没搞透彻,说实话,之前借的汇编书讲解的实在有些烂,NND连个上机调试的方法都没有。学东西,找一本好书还是蛮重要的。

    invoke伪指令其实是MASM为了我们方便调用API,只是把我们的书写格式简单化了。当程序编译后,编译器还是会把它汇编成几条push语句和一条call语句,所以它和先push参数后call的结果是没有差别的。
    以两个最简单的HelloWorld为例来比较。

    ;FILE:MSG-A.ASM

    .386
    .model flat,stdcall
    option casemap:none

    include     windows.inc
    include     user32.inc
    includelib user32.lib
    include     kernel32.inc
    includelib kernel32.lib

    .data
    sztitle db 'By Invoke!',0
    szctent db 'Hello,zerosoul!',0

    .code
    start:
    lea eax,sztitle
    lea ebx,szctent
    invoke MessageBox,NULL,ebx,eax,MB_OK
    invoke ExitProcess,NULL
    end start

    ;MSG-B.ASM

    .386
    .model flat,stdcall
    option casemap:none

    include     windows.inc
    include     user32.inc
    includelib user32.lib
    include     kernel32.inc
    includelib kernel32.lib

    .data
    sztitle db 'By Push!',0
    szctent db 'Hello,zerosoul!',0

    .code
    start:
    lea eax,sztitle
    lea ebx,szctent
    push MB_OK
    push eax
    push ebx
    push NULL
    call MessageBox
    push NULL
    call ExitProcess
    end start

    这两个HelloWorld的区别就是A程序直接用invoke调用API,B程序先push参数,然后用call函数。

    为了保持程序的一致性,我都先把参数地址用
    lea eax,sztitle,lea ebx,szctent传入了eax,ebx。
    然后用ml /c /coff MSG-1.ASM,link /subsystem:windows MSG-A.obj,分别编译和连接这两个程序,双击运行正常

    然后我们把这连个程序分别放到OllyDBG里面反汇编看看它们的机器码,结果证明他们编译以后的机器码几乎是完全一样的!

    Tips:用call调用函数后,很多人会想到堆栈平衡的问题。由于我们这里用的是StdCall,堆栈平衡的工作由子程序来完成,所以我们调用的时候可以不用使用add ESP,8这样的语句手动恢复堆栈。

  • 相关阅读:
    Wix Burn:如何将32位和64位的安装包制作成一个安装包
    禁止32位安装包运行在64位操作系统上
    图片校验码
    Oracle建表命令
    npm系列
    git使用
    syslog
    hibernate配置enum枚举属性
    httpClient发送post请求
    修改ubuntu系统语言
  • 原文地址:https://www.cnblogs.com/milantgh/p/3863843.html
Copyright © 2011-2022 走看看