管理博客 ┆ 搜索 ┆ 帮助
Windows汇编语言简明教程——基础篇(2)
作者:tbsoft工作室 2007-04-13 10:51:14
标签:
 

4 非结构化的汇编语言和结构化的汇编语言

 

读者可能一听到“汇编语言”四个字就觉得十分头疼!汇编语言给人的第一印象就是一大堆难以看懂又不直观的指令,而且不结构化,大量的标号、无条件跳转指令(JMP)和条件跳转指令让你难以看懂程序;过程(或者函数)的调用参数传递又不直观,要么直接使用寄存器传递参数,不符合结构化程序设计原则;要么使用堆栈传递参数,又不能有效地检验参数类型……想必Win32汇编语言更麻烦吧!

 

汇编语言不是结构化编程语言,但不等于汇编语言不能进行结构化编程,MASM 6.0以上版本的汇编器对汇编语言进行了扩展,提供了很多结构化汇编语言伪指令,可以方便地实现汇编语言结构化程序设计,当你看完本教程以后,你可能会感觉到:Win32汇编语言并不比C语言麻烦多少。(如果读者看不懂本教程中的汇编语言源程序,可以对照MASM32中有关结构化汇编语言语法的帮助看)

 

下面是一个使用非结构化的汇编语言编写的Win32汇编语言程序,本程序没有使用结构化汇编语言伪指令。本程序的功能很简单:在屏幕上显示一个消息框。本程序只调用了两个Win32 API:MessageBox和ExitProcess,源程序如下(MSGBOX1.asm):

 

.386

 

.MODEL flat,stdcall

 

OPTION CASEMAP:NONE

 

INCLUDE \masm32\include\windows.inc

 

INCLUDE \masm32\include\kernel32.inc

INCLUDE \masm32\include\user32.inc

 

INCLUDELIB \masm32\lib\kernel32.lib

INCLUDELIB \masm32\lib\user32.lib

 

.STACK 4096

 

.DATA

    MsgText         BYTE        'This is a simple Win32 application!',0

    MsgTitle        BYTE        'Information',0

  

.CODE

 

_start:

    mov     eax,MB_ICONINFORMATION

    or      eax,MB_OK

    push    eax

    lea     eax,MsgTitle

    push    eax

    lea     eax,MsgText

    push    eax

    xor     eax,eax

    push    eax

    call    MessageBox

    xor     eax,eax

    push    eax

    call    ExitProcess

 

END _start

 

使用Quick Editor汇编链接本程序的基本方法如下(下同):

 

1、启动MASM32中的Quick Editor,编辑汇编语言源程序,将上述汇编语言源程序全部输入或者粘贴,然后选择“File”—“Save As”菜单项将汇编语言源程序保存到一个目录下,注意该目录必须与MASM32的安装目录位于同一个驱动器上,汇编语言源程序文件的扩展名应该是“asm”。

 

2、选择Quick Editor中的“Project”—“Build All”菜单项即可汇编链接汇编语言源程序。汇编链接时会显示一个命令提示符窗口,如果没有出现错误或者警告信息,说明汇编链接成功,将会生成相应的OBJ文件和EXE文件。

 

3、选择Quick Editor中的“Project”—“Run Program”菜单项即可运行汇编链接后生成的EXE文件。

 

本程序汇编链接后,运行生成的MSGBOX1.exe文件,屏幕上将显示出一个消息框,消息框的标题是“Information”,消息框中显示的字符串是“This is a simple Win32 application!”。

 

Win32汇编语言源程序开始处通常有3条伪指令:

 

.386

 

.MODEL flat,stdcall

 

OPTION CASEMAP:NONE

 

指示汇编器汇编80386指令,并使用平坦内存模式(Win32内存模式)和stdcall函数调用方式(Win32标准函数调用方式),标识符区分大小写。源程序中使用.STACK、.DATA和.CODE伪指令分别定义堆栈、数据和代码。

 

Win32 API通常使用stdcall函数调用方式,stdcall函数调用方式中,函数的参数使用堆栈传递,函数调用之前参数自右向左进栈,函数调用返回时同时将参数出栈,函数返回值通过eax寄存器返回。

 

因此,程序中调用MessageBox函数和ExitProcess函数之前,都使用push指令将参数自右向左进栈,然后使用call指令直接调用Win32 API的入口点地址。本程序调用MessageBox函数显示消息框以后,调用ExitProcess函数终止程序的执行,ExitProcess函数的作用是终止当前进程。这种直接使用汇编语言指令调用Win32 API开发Win32应用程序的方式直接对应CPU的指令代码,最接近CPU硬件,但并不直观,编写程序一不小心就容易出错。

 

下面是一个与上述程序等价的Win32汇编语言源程序,使用了结构化汇编语言伪指令,实现了结构化的汇编语言。源程序如下(MSGBOX2.asm):

 

.386

 

.MODEL flat,stdcall

 

OPTION CASEMAP:NONE

 

INCLUDE \masm32\include\windows.inc

 

INCLUDE \masm32\include\kernel32.inc

INCLUDE \masm32\include\user32.inc

 

INCLUDELIB \masm32\lib\kernel32.lib

INCLUDELIB \masm32\lib\user32.lib

 

.STACK 4096

 

.DATA

    MsgText         BYTE        'This is a simple Win32 application!',0

    MsgTitle        BYTE        'Information',0

  

.CODE

 

_start:

    INVOKE  MessageBoxA,0,ADDR MsgText,ADDR MsgTitle,MB_ICONINFORMATION or MB_OK

    INVOKE  ExitProcess,0

 

END _start

 

本程序汇编链接后,运行生成的MSGBOX2.exe文件,结果与MSGBOX1.exe文件的运行结果完全相同。

 

在MASM32提供的包含文件中,使用PROTO伪指令定义函数原型(与C语言中函数原型的定义相似),可以定义函数名、调用方式和参数,例如在user32.inc包含文件中定义MessageBox的函数原型:

 

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

MessageBox equ <MessageBoxA>

 

INVOKE伪指令调用由PROTO伪指令定义的函数,可以方便地传递参数和检查参数类型。包含文件中使用PROTO伪指令定义API函数,MSGBOX2.asm文件中使用INVOKE伪指令调用API函数,极其简单,连一条汇编语言指令也没有用到,可见MASM 6.0以上版本的汇编器提供的结构化汇编语言伪指令大大简化了Win32汇编语言编程。

 

本文仅为提供更多信息,不代表新浪BLOG同意其观点或描述。如需转载请注明出处。