汇编语言程序例USTC.docx

上传人:b****6 文档编号:9049265 上传时间:2023-02-02 格式:DOCX 页数:33 大小:76.61KB
下载 相关 举报
汇编语言程序例USTC.docx_第1页
第1页 / 共33页
汇编语言程序例USTC.docx_第2页
第2页 / 共33页
汇编语言程序例USTC.docx_第3页
第3页 / 共33页
汇编语言程序例USTC.docx_第4页
第4页 / 共33页
汇编语言程序例USTC.docx_第5页
第5页 / 共33页
点击查看更多>>
下载资源
资源描述

汇编语言程序例USTC.docx

《汇编语言程序例USTC.docx》由会员分享,可在线阅读,更多相关《汇编语言程序例USTC.docx(33页珍藏版)》请在冰豆网上搜索。

汇编语言程序例USTC.docx

汇编语言程序例USTC

第1章Windows汇编语言程序设计基础

Windows汇编语言程序分为控制台编程和图形界面编程两种,控制台编程相对简单一些。

为了由浅入深,本书从控制台编程开始讲解。

读者总希望用最快的速度掌握书中的概貌,为此从一个最简单的程序开始。

一些汇编语言语法也结合程序进行讲解,有些指令和语法用注解的方法说明。

1.1第一个完整的Windows汇编语言程序

Windows汇编语言程序有自己的编程规范,它的编程规范比VisualC要简单得多,调试也很方便。

更重要的是系统把重要的东西都呈现给读者,使读者更能掌握其中的本质。

用一条一条的汇编语言指令很难写出大程序,Windows汇编语言程序也是调用系统提供的API来写程序。

因而,用Windows汇编语言同样可写出大程序。

以下是一个最简单的Windows程序。

;程序功能:

显示一个信息框。

;ex1.asm(e:

\masm\base);程序名

;编译链接方法:

;ml/c/coffex1.asm

;link/subsystem:

consoleex1.obj

.386;指明指令集

.modelflat,stdcall;程序工作模式,flat为Windows程序使用的模式(代码和数据

;使用同一个4GB段),stdcall为API调用时右边的参数先入栈

optioncasemap:

none;指明大小写敏感

includewindows.inc

includeuser32.inc

includelibuser32.lib

includekernel32.inc

includelibkernel32.lib

.data;数据段

szCaptiondb'抬头串',0

szTextdb'Hello!

',0

.code;代码段

start:

invokeMessageBox,;显示信息框

NULL,;父窗口句柄

offsetszText,;正文串的地址

offsetszCaption,;抬头串的地址

MB_OK;按钮

invokeExitProcess,;终止一个进程

NULL;退出代码

endstart;指明程序入口点

程序运行结果见图1-1。

图1-1

说明:

程序调用了两个Windows提供的API。

invoke是汇编语言中的伪指令,该指令的使用方法见1.4节。

1.2编译、链接和运行

1.2.1创建编译链接环境

(1)安装MASM615调试工具。

(2)建立一个VAR.BAT文件,内容如下。

@echooff

rem请根据Masm32软件包的安装目录修改下面的Masm32Dir环境变量!

setMasm32Dir=c:

\Masm32

setinclude=%Masm32Dir%\Include;

c:

\ProgramFiles\MicrosoftVisualStudio\VC98\Include;(本行应接在上行后)

ProgramFiles\MicrosoftVisualStudio\VC98\MFC\Include;(本行应接在上行后)

%include%(本行应接在上行后)

setlib=%Masm32Dir%\lib;%lib%

setw2k=%Masm32Dir%\Incluse\w2k;%Include\w2k%

setpath=%Masm32Dir%\Bin;%Masm32Dir%\Include;%Masm32Dir%\Include\w2k;

%Masm32Dir%\lib;%Masm32Dir%;%PATH%(本行应接在上行后)

setMasm32Dir=

echoon

编译链接程序前,需要切换到命令提示符方式,并运行该文件(设置好环境),然后方可进行编译链接。

1.2.2编译链接和运行

以下以编译链接ex1.asm为例:

(1)编译。

ML/Zi/c/Fl/coffex1.asm

ML参数说明(注意参数大小写):

/Zi––加符号调试信息

/c––连接前的编译

/Fl––F1[file]产生列表文件

/coff––产生COFF格式目标文件

编译的更多参数说明,可用命令ML/?

查阅。

(2)链接。

LINK/SUBSYSTEM:

consoleex1.obj

其中console指明是控制台编程,如果是Windows窗口编程,则将console改为Windows。

(3)运行。

在Windows下双击ex1.exe或在DOS命令提示符下键入ex1回车。

1.2.3建立编译链接批命令文件

可以把编译链接过程写成批命令文件,以减少键盘输入量。

例如:

MLEXE.BAT

ML/Zi/c/Fl/coff%1.asm

LINK/subsystem:

console%1.obj

del%1.obj

dir%1.*

如果要编译链接ex1.asm,则只需输入:

MLEXEex1回车

1.3将Windows汇编语言程序反汇编后的程序原形

将可执行程序用IDA反汇编工具反汇编后,程序的代码部分可直接使用,程序的其他部分稍作修改后,即可再编译链接成可执行程序。

具体修改部分见程序尾的说明。

;iex1.asm,本程序为ex1.exe反汇编后的程序。

;iex1.asm(e:

\masm\base)

;编译链接方法:

;ml/c/coffiex1.asm

;link/subsystem:

Windowsiex1.obj

.386

.modelflat,stdcall

optioncasemap:

none

.data

includewindows.inc

includeuser32.inc

includelibuser32.lib

includekernel32.inc

includelibkernel32.lib

Captiondb'抬头串',0

Textdb'Hello!

',0

.code

publicstart

startprocnear

push0;uType

pushoffsetCaption;"抬头串"

pushoffsetText;"Hello!

"

push0;hWnd

callMessageBoxA

push0;uExitCode

callExitProcess

startendp

endstart

说明:

API调用时右边的参数先入栈。

用反汇编工具IAD反汇编后,保留代码段不变,将数据段中的数据搬入代码段,将其余部分删除,再加入包含文件和程序中的前4条指令,即可再编译链接成可执行程序。

将可执行文件反汇编成汇编语言程序,经过适当修改后,再编译链接成可执行文件,这是十分有意义的。

1.4invoke伪指令的使用格式、变量及数据段data

和data?

的区别

1.4.1invoke伪指令的使用格式

invoke伪指令的使用格式为:

invoke函数名[,参数1][,参数2]...

参数的个数不定,可以没有,也可以有多个。

如果invoke与某个函数的参数个数不匹配(少或多),则编译时报错。

如果参数个数少,则报错“errorA2137:

toofewargumentstoINVOKE”;如果参数个数多,则报错“errorA2137:

toomanyargumentstoINVOKE”。

1.4.2变量

1.变量的命名规则

变量由大写字母A,B,…,Z,小写字母a,b,…,z,数字0,1,2,…,9,下划线,符号@、$和?

组成,且变量的第一个符号不能是数字。

变量的长度不能超过240个字符,不能使用指令名关键字,在同一个作用域内不能重名。

应该养成良好的命名习惯,如表1-1所示。

表1-1

缩写

含义

缩写

含义

sz

表示以0结尾的字符串(ASCIIZ)

lp

表示指针longpoint

h

表示句柄handle

lpsz

表示指向ASCIIZ的指针

b

表示字节byte

f

表示浮点数float

w

表示字word

st

表示结构体struct

dw

表示双字doubleword

例如:

hWin表示窗口句柄

lpArray表示指向数组的指针

szString以0结尾的字符串

stWndClassWNDCLASS结构

bNumber以字节定义的数

dwNumber以双字定义的数

wNumber以字定义的数

2.全局变量

全局变量的作用域为整个程序。

在 .data和 .data?

段内定义的变量为全局变量。

全局变量的定义格式为:

变量名类型初始值

变量名类型重复数量dup(初始值)

例如:

countdw0

arraydb10dup(0)

3.局部变量

局部变量的作用域为一个程序内。

局部变量的定义格式为:

local变量名1[重复数量][:

类型],变量名2[重复数量][:

类型]...

局部变量要放在子程序的开始位置,并且没有初始值。

例如:

.386

.modelflat,stdcall

optioncasemap:

none

includewindows.inc

includekernel32.inc

includelibkernel32.lib

.code

SubProcproc,x:

byte,y:

byte

locala:

byte;定义局部变量

localb:

byte;定义局部变量

moval,x

mova,al

moval,y

movb,al

ret

SubProcendp

mainproc

invokeSubProc,1,2;调用子程序(右边参数先入栈)

invokeExitProcess,0;退出进程

mainendp

endmain

4.局部变量在栈中的位置

将以上程序用IDA反汇编后的程序如下:

sub_401000procnear

var_2=byteptr-2

var_1=byteptr-1

arg_0=byteptr8

arg_4=byteptr0Ch

pushebp

movebp,esp

addesp,0FFFFFFFCh;(-4)的补码=0FFFFFFFCh

moval,[ebp+arg_0];x=1

mov[ebp+var_1],al

moval,[ebp+arg_4];y=2

mov[ebp+var_2],al

leave

retn8;将入口参数(x,y)退栈

sub_401000endp

publicstart

startprocnear

push2

push1

callsub_401000

push0

call$+5

jmpds:

ExitProcess

startendp

说明:

参数在栈中的位置见图1-2。

图1-2栈区示意图

1.4.3数据段data和data?

的区别

程序的一般结构为:

.data

定义变量并初始化(有初始值)

.data?

定义变量(变量的初始值为'?

')

.const

定义常量

.code

定义在 .data?

段中的变量的初始值只能是'?

'。

定义在 .data?

段中的变量不占用磁盘空间,即不增加 .exe文件的大小。

这是用 .data?

段的优点。

例如,在 .data?

中定义变量:

.data?

sumdw?

array10dbdup(?

在实际应用中,上述变量的初始值为0。

汇编语言中的类型如表1-2所示。

表1-2

缩写

全名写法

名称和字节数

db

byte

字节(1字节)

dw

word

字(2字节)

dd

dword

双字(4字节)

df

fword

三字(6字节)

dq

qword

四字(8字节)

dt

tbyte

10字节BCD码

sbyte

有符号字节(1字节)

sword

有符号字(2字节)

sdword

有符号双字(4字节)

real4

单精度实型数(4字节)

real8

双精度实型数(8字节)

real10

10字节实型数(10字节)

1.4.4高级语法while-endw的使用

while-endw的格式为:

.while(条件)

偱环体(条件满足时执行)

.endw

;ex2.asm(e:

\masm\base)高级语法while-endw的使用示例。

;程序功能:

用while偱环给字节数组赋值并计算。

.386

.modelflat,stdcall

optioncasemap:

none

includewindows.inc

includekernel32.inc

includelibkernel32.lib

includeuser32.inc

includelibuser32.lib

.data

adb10dup(0);定义字节数组

bufferdb10dup(0)

CapMsgdb'输出',0

szFmtdb'结果是:

%d',0

idb0

sumdb0

.code

start:

movedi,0

.while(i<10)

moval,i

mova[edi],al

inci

incedi

.endw

movi,0

movedi,0

.while(i<10)

moval,a[edi]

addsum,al

inci

incedi

.endw

xoreax,eax

moval,sum

invokewsprintf,;格式化信息串

addrbuffer,;信息串格式化后的存放地

addrszFmt,;信息串的格式:

"结果是:

%d",0

eax;二进制数

invokeMessageBox,;显示信息框

NULL,;父窗口句柄

offsetbuffer,;正文串"结果是:

%d",0

offsetCapMsg,;抬头串"输出",0

MB_OK;按钮"确定"

INVOKEExitProcess,0;结束进程

endstart

运行结果见图1-3。

图1-3

1.4.5高级语法repeat-until的使用

repeat-until的格式为:

.repeat

偱环体(条件不满足时执行)

.until(条件)

;ex3.asm(e:

\masm\base)高级语法repeat-until的使用。

;程序功能:

用repeat偱环给双字数组赋值并计算。

.386

.modelflat,stdcall

optioncasemap:

none

includewindows.inc

includekernel32.inc

includelibkernel32.lib

includeuser32.inc

includelibuser32.lib

.data

add10dup(0);定义双字数组

bufferdb10dup(0)

CapMsgdb'输出',0

szFmtdb'结果是:

%d',0

idd0

sumdd0

.code

start:

movedi,0

.repeat

moveax,i

mova[edi],eax

inci

addedi,4

.until(i>=10)

movi,0

movedi,0

.repeat

moveax,a[edi]

addsum,eax

inci

addedi,4

.until(i>=10)

moveax,sum

invokewsprintf,;格式化信息串

addrbuffer,;信息串格式化后的存放地

addrszFmt,;信息串的格式:

"结果是:

%d",0

eax;二进制数

invokeMessageBox,;显示信息框

NULL,;父窗口句柄

offsetbuffer,;正文串"结果是:

%d",0

offsetCapMsg,;抬头串"输出",0

MB_OK;按钮"确定"

INVOKEExitProcess,0;结束进程

endstart

运行结果见图1-3。

1.4.6高级语法if-elseif-endif的使用

if-elseif-endif的格式为:

.if条件1

指令(条件1满足时执行)

[.elseif条件2]

指令(条件2满足时执行)

[.elseif条件3]

指令(条件3满足时执行)

endif

;ex4.asm(e:

\masm\base)高级语法if-elseif-endif的使用。

;程序功能:

输出"number是正数"或"number是负数"。

.386

.modelflat,stdcall

optioncasemap:

none

includewindows.inc

includekernel32.inc

includelibkernel32.lib

includeuser32.inc

includelibuser32.lib

.data

CapMsgdb'输出',0

szFmtdb'number是正数:

%d',0

szFmt2db'number是负数:

%d',0

numberdd-9

bufferdb80dup(0)

.code

start:

moveax,number

invokewsprintf,;格式化信息串

addrbuffer,;信息串格式化后的存放地

addrszFmt,;'number是正数',0

eax;二进制数

moveax,number

.ifeax==-9

invokewsprintf,;格式化信息串

addrbuffer,;信息串格式化后的存放地

addrszFmt2,;'number是负数',0

eax;二进制数

.endif

invokeMessageBox,;显示信息框

NULL,;父窗口句柄

offsetbuffer,;正文串"结果是:

%d",0

offsetCapMsg,;抬头串"输出",0

MB_OK;按钮"确定"

INVOKEExitProcess,0;结束进程

endstart

运行结果见图1-4。

图1-4

1.4.7条件运算符

汇编语言中的条件运算符和高级语言的条件运算符类似,这给编写程序带来了极大的方便。

条件运算符如表1-3所示。

表1-3

条件运算符

功能

说明

==

等于

变量和操作数之间的比较

!

=

不等于

变量和操作数之间的比较

<

小于

变量和操作数之间的比较

>

大于

变量和操作数之间的比较

<=

小于等于

变量和操作数之间的比较

>=

大于等于

变量和操作数之间的比较

&&

逻辑与

两个表达式的结果

||

逻辑或

两个表达式的结果

&

按位与

变量和操作数的结果

!

取反

变量或表达式的结果

条件运算时,非零为真,零为假。

条件运算时,要注意表达式的左边应为寄存器或变量,不能为常数,表达式两边可以同时为寄存器,但不能同时为变量。

标志测试伪指令:

CARRY?

表示进位标志是置位

ZERO?

表示零标志是置位

SIGN?

表示符号标志是置位

PARITY?

表示奇偶标志是置位

OVERFLOW?

表示溢出标志是置位

;ex5.asm(e:

\masm\base)条件运算符的使用。

.386

.modelflat,stdcall

optioncasemap:

none

includewindows.inc

includekernel32.inc

includelibkernel32.lib

includeuser32.inc

includelibuser32.lib

.data

CapMsgdb'输出',0

szFmtdb'eax=%d(eax==1满足),ebx=%d(置进位标志),edx=%d(edx为零满足)',0

bufferdb80dup(0)

.code

start:

moveax,1

.ifeax==1

moveax,2

.endif

movebx,10

stc;置进位标志

.ifCARRY?

;进位标志是置位?

movebx,20

.endif

xoredx,edx;使零标志置位(为1)

.if!

ZERO?

;零标志不是置位?

movedx,8

.endif

invokewsprintf,;格式化信息串

addrbuffer,;信息串格式化后的存放地

addrszFmt,;格式化串

eax,;数

ebx,

edx

invokeMessageBox,;显示信息框

NULL,;父窗口句柄

offsetbuffer,;正文串

offsetCapMsg,;抬头串"输出",0

MB_OK;按钮"确定"

INVOKEExitProcess,0;结束进程

endstart

运行结果见图1-5。

图1-5

1.4.8高级语法continue的使用

continue用在偱环while-endw和repeat-until中,它的功能是结束本次偱环(continue语句后的语句不执行),进入下一次偱环。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1