一个win32汇编语言程序示例

首先我们看一个“复杂”的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啦!;stadcall,标准调用
option casemap:none ;区别大小写

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

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

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

.data;数据区,定义2个字符串
szText db "Hello, world!",0
szCaption db "Win32Asm",0

.code ;代码开始执行处
start:
invoke MessageBox,NULL,addr szText,addr szCaption,MB_OK 

;调用MessageBoxAPI函数
invoke ExitProcess,NULL ;程序退出
end start;结束
------------------------------------
编译链接:
ml /c /coff /I d:\masm7\include 3.asm ;注意开关符识别大小写

时间: 2024-11-02 05:44:25

一个win32汇编语言程序示例的相关文章

《C Primer Plus(第6版)中文版》一第2章 C语言概述2.1 简单的C程序示例

第2章 C语言概述 C Primer Plus(第6版)中文版 本章介绍以下内容: 运算符:= 函数:main().printf() 编写一个简单的C程序 创建整型变量,为其赋值并在屏幕上显示其值 换行字符 如何在程序中写注释,创建包含多个函数的程序,发现程序的错误 什么是关键字 C程序是什么样子的?浏览本书,能看到许多示例.初见C程序会觉得有些古怪,程序中有许多{.cp->tort和*ptr++这样的符号.然而,在学习C的过程中,对这些符号和C语言特有的其他符号会越来越熟悉,甚至会喜欢上它们.

c++ win32编...-我写了一个win32项目的小程序 如何发给别人自动正常运行

问题描述 我写了一个win32项目的小程序 如何发给别人自动正常运行 把写好的程序打包为exe文件 但是发给朋友显示缺少库文件 然后在程序本身的文件夹中并没有库文件啊 百度一下很多说应该把debug版本改为release版本 改过之后依旧不行 本人新手刚接触win32程序 怎么办 解决方案 程序研究+写花了一天 调试运行在我电脑上都好好的 一发给别人就不行了 好尴尬

汇编语言-有没有汇编的大神帮帮忙,一个简单的程序。。。。。跪求,好人一生平安

问题描述 有没有汇编的大神帮帮忙,一个简单的程序.....跪求,好人一生平安 ;子程序名:在字符串1后面追加字符串2,设字符串均以0结束 ;功 能:在字符串1末追加字符串2 ;入口参数:DS:SI=字符串1起始地址的段值:偏移 ; DS:DI=字符串2起始地址的段值:偏移 ;出口参数:无 ;说 明:不考虑在字符串1后是否留有足够的空间 STRCAT PROC PUSH ES PUSH AX PUSH CX PUSH SI PUSH DI CLD PUSH DS POP ES ;使ES同DS PU

VC++基于Dx实现的截图程序示例代码_C 语言

本文所述的程序示例为VC++图象特效的截图示例,需要DirectX 3.0以上版,代码中的GetScreen函数是本截图程序的关键.运行这个程序可用Esc键结束.代码中需要ddutil.h与ddutil.cpp文件,请自行下载添加.关于InitDDraw()函数,功能是初始化DirectDraw环境,创建换页链(主页面,一个后台缓冲区),以及创建一个定时器. 具体的功能代码如下: #include <windows.h> #include <windowsx.h> #include

VC++的win32小程序内存泄漏,求高手解答

问题描述 VC++的win32小程序内存泄漏,求高手解答 做的一个简单的交通模拟小程序,用三个定时器分别产生 汽车处理消息,红绿灯更换消息和汽车随机产生消息.但是最后程序内存越跑越大.求高手解答.http://download.csdn.net/detail/hdwbdbsm/6724747这个是程序的下载地址,求高手.

利用HttpRequest登录到某个网站,然后获取网站信息的程序示例 [原创]

request|程序|示例|原创 问题:有的网站的相关内容必须要在登录后才可以查看,其登录信息保存在session变量之中.这样,使用asphttp等组件就难以正确得到所要的信息. 解决:使用asp.net中的httprequest和httpresponse来实现. 要点:1. 通过附加一个cookiecontainer到httprequest对象中,可以得到登录后返回的代表SESSION ID的COOKIE. 见Login方法2. 将此COOKIE包含在一个cookiecontainer中并附

PHP写的一个简单的cache示例

一个简单的cache示例(不过太简单了一些!) ?// 首先创建"cache"目录 ,用来写文件 function BZ_cache ($url,$cacheName)?? { global $cache ;?? global $QUERY_STRING ; // 这里你可以按自己的习惯命名?? $filename = "cache/".$cacheName.",".$QUERY_STRING.".HTML" ; // 这里你

对应用程序结构进行组织的程序示例

上面我们介绍了对应用程序结构进行组织的方法,接下来我们举一个综合应用的例子.程序实现的功能非常简单,但其中用到了我们讲解的各方面的知识.在程序中,我们利用名字空间把应用程序功能进行分割,并且用到了在一个名字空间中包含多个类.在一个可执行文件中调用多个动态链接库的方法.程序中还用到了异常处理.类的继承.派生类对虚方法的重载.多态性的实现等概念,希望读者能够在阅读程序时认真注意这些用法,来加深对基本概念的理解. 该程序是一个小游戏,游戏中随机产生矩形.正方形.直角三角形.等腰直角三角形四种图形.游戏

使用.NET发送E-Mail小程序示例

本文主要是以.NET下怎么实现发送E-Mail作为示例分析讲解,故在示例程序里有许多涉及到.Net.Mail之外的内容都没做.最近比较忙没太多的时候去完善其功能,有兴趣的朋友可以下载源码去完善下.这不是一个什么大的软件,也不是什么很特别的东西,我写这个文章的目的是让大家一起来学习.NET下发送E-mail的实现,希望这篇文章可以帮助到还没搞清楚怎么实现发送邮件的朋友,对于已经会的或是这方面的牛人的前辈们看了本文请留下宝贵的建议. 本程序是采用.NET框架下的Mail类来完成邮件的发送操作的,里面