庞大资源库的计算机教程网站!
设为首页
加入收藏
总编信箱
投稿或申请专栏请先 [登 陆]
首页 操作系统 程序设计 图形图像 媒体动画 机械电子 WEB开发 数 据 库 办公系列 路由技术 网络原理 网络应用
认证考试 安全技术
首页>程序设计>汇编语言>技巧教程>正文
资料搜索
Google搜索
Google
返回上级列表

推荐文章

快速保存网页中所有图片的方法
Windows中让光驱巧妙“隐身”技
防范非法用户入侵Win 2000/XP系
两款比较典型的ASP木马防范方法
有关表格边框的css语法整理
Windows XP中可以被禁用的服务
SQL Server导出导入数据方法
Javascript所有对象的属性的获
网页(HTML)中的特殊字符
与篮球共舞,尽显模式本色
QQ病毒的手工清除方法
Photoshop为极品美女打造性感睫
天衣无缝:IIS与PHP水火也相容
SQL Server存储过程编写和优化

小试Win32汇编

 作者:本站收集   日期:2005-8-1 15:50:48
字号选择〖 〗/ 双击滚屏 单击停止   

   首先我们看一个“复杂”的Win32汇编程序
程序用来显示一个消息框

--------------------------------------------------
;文件名:3.asm

        .386
        .model flat ,stdcall

NULL    equ 0
MB_OK   equ 0

ExitProcess PROTO :DWORD
MessageBoxA PROTO :DWORD,:DWORD,:DWORD,:DWORD

includelib kernel32.lib
includelib user32.lib

          .data
szText    db "Hello, world!",0
szCaption db "Win32Asm",0

        .code
start:
        push MB_OK
        lea eax,szCaption
        push eax
        lea eax,szText
        push eax
        push NULL
        call messageboxa
        xor eax,eax
        push eax
        call exitprocess
        end start
--------------------------------------------------
编译链接:
    分下面两步进行:
        ml   /c /coff 3.asm  
        link /subsystem:windows /libpath:d:\masm7\lib 3.obj
        
    第一步编译生成3.obj文件
    /c 表示只编译,不链接
    /coff 表示生成COFF格式的目标文件
    
    第二步链接生成3.exe文件
    /subsystem:windows 表示生成windows文件
    /libpath:d:\masm7\lib 表示引入库的路径为:d:\masm7\lib。
    在安装Masm32后,引入库位于Masm32\Lib目录下。
    
    也可设置环境变量Lib的值:在dos提示符下键入Set Lib=d:\masm7\lib,这样“链接”就可简单写成:
    link /subsystem:windows 3.obj,试想一下,在程序调试过程中,修改源程序是常用的事啦,每次编译链接都要带/libpath:...那该有多烦人呢。当然,我们也可在源程序中直接给出引入库的位置,这样,链接时就方便啦,如下:
    
    includelib d:\masm7\lib\kernel32.lib
    includelib d:\masm7\lib\user32.lib
--------------------------------------------------
执行:在dos提示符下键入3,回车,出现一个消息框,哈哈,真正的Win32程序!

      

--------------------------------------------------
深入分析:
    看一下源程序,有这么两行:call messageboxa\call exitprocess。大家一看都知道,这是子程序调用,但是我们并没写这样的子程序,事实上,这些是API函数。作为函数,我们在调用时可能需要传送给函数一些参数,程序怎么知道传送的参数有哪些,类型是什么呢?就是通过函数原型定义,如下所示:
    ExitProcess PROTO :DWORD
    MessageBoxA PROTO :DWORD,:DWORD,:DWORD,:DWORD
    可以看出,ExitProcess有一个参数,MessageBoxA有四个参数,这些参数都是DWORD类型。
    
    在Win32中,参数的传递都是通过堆栈来完成的。象MessageBoxA这个函数有四个参数,究竟是左边的先压入堆栈还是右边的先入栈呢?.model flat,stdcall给出了答案。stdcall 指定参数是从右到左压入堆栈的,且调整堆栈是在子程序返回时完成的。在源程序中不需要用“add sp,值”来保持堆栈平衡。对MessageBox,在API手册中是这样定义的:
        int MessageBox(
            HWND hWnd,          // handle of owner window
            LPCTSTR lpText,     // address of text in message box
            LPCTSTR lpCaption,  // address of title of message box
            UINT uType          // style of message box
            )
      ;所以会有我们的程序段:
        push MB_OK
        lea eax,szCaption
        push eax
        lea eax,szText
        push eax
        push NULL
        call messageboxa

    看看上面的程序,不难想到,假如在写程序时,少往堆栈里压入一个数据,那将是一个致命的错误。能不能将这种检查参数个数是否匹配的工作交给计算机来完成呢?这是可以的,INVOKE指令可以帮助我们完成这样的工作。假如你的参数个数不正确,连接器将给出错误提示。所以,极力建议你使用invoke代替call来调用子程序,当然,这不是绝对的。使用invoke上面的指令就可简写成下面的样子,看起来简炼多啦,查错也方便啦!
        invoke messageboxa, NULL,addr szText,addr szCaption,MB_OK

   另外,像NULL,MB_OK都是一些常量,这样的常量有很多,还有很多的结构,如果在我们的程序中一开始都写这么多的东西,可能一下子就把你吓怕啦,也容易出错,更不便于看程序的主要部分。hutch整理的windows.inc包含了WIN32编程所需要的常量和结构体的定义,我们可简单的用一个include指令将这些常量和结构的定义插入到我们的文件中:
        include d:\masm32\include\windows.inc
  
   但是windows.inc中并不包含函数原型的声明,还要从其他的头文件中得到函数原型的声明,比如:messageboxa的原型声明在user32.inc文件中,exitprocess在kernel32.inc文件中。这些头文件都放在 \masm32\include文件夹下。
  
   还有,要用windows.inc,必须使用option casemap:none,它的意思是告诉 MASM 要区分符号的大小写,譬如:start和START是不一样的。否则,一个小小的程序,可能会出成百上千的错误呀!
  
   其他的,就不再细说啦,到此,上面的程序可重新修改如下:
-----------------------------------------------------------------
;最终的结果
        .386                    ;表示要用到386指令
        .model flat,stdcall     ;32位程序,要用flat啦!
        option casemap:none     ;区别大小写

include    windows.inc  ;常量及结构定义

include    kernel32.inc ;函数原型声明
include    user32.inc

includelib kernel32.lib ;用到的引入库
includelib user32.lib

          .data
szText    db "Hello, world!",0
szCaption db "Win32Asm",0

        .code
start:
        invoke MessageBox,NULL,addr szText,addr szCaption,MB_OK
        invoke ExitProcess,NULL         ;程序退出
        end start
------------------------------------
编译链接:
        ml   /c /coff /I d:\masm7\include 3.asm   ;注意开关符识别大小写
        link /subsystem:windows /libpath:d:\masm7\lib 3.obj
        
        /I d:\masm7\include 表示*.inc文件的位置,也可设置环境变量Set include=d:\masm7\include来简化操作,也可在程序中明确指出*.inc的位置。
        
    前面讲的都是用两条指令来完成编译链接,实际上用一条指令也可完成,如下:
    ml /coff /I d:\masm7\include 3.asm /link /subsystem:windows /libpath:lib
    若*.inc及引入库在源程序中都明确指出其位置,则可简化为:
    ml /coff 3.asm /link /subsystem:windows
    
    累,先写到这儿吧!

上一篇:Windows下控制台输出    下一篇:DOS下的EXE格式文件  
[发送给好友]  [关闭窗口]  [返回顶部]   转载请注明来源:www.it00.com   
特别声明: 本站除部分特别声明禁止转载的专稿外的其他文章可以自由转载,但请务必注明出处和原始作者。文章版权归文章原始作者所有。对于被本站转载文章的个人和网站,我们表示深深的谢意。如果本站转载的文章有版权问题请联系编辑人员,我们尽快予以更正。
责任编辑: 原点 投稿作者: 本站收集
信息来源: 网络 录入时间: 2005-8-1 15:50:48
关于我们 - 广告服务 - 版权申明 - 网站地图 - 联系方式 - 总编信箱 - 会员投稿