汇编语言程序例 - USTC.doc

上传人:罗晋 文档编号:11797945 上传时间:2021-09-14 格式:DOC 页数:21 大小:199KB
返回 下载 相关 举报
汇编语言程序例 - USTC.doc_第1页
第1页 / 共21页
汇编语言程序例 - USTC.doc_第2页
第2页 / 共21页
汇编语言程序例 - USTC.doc_第3页
第3页 / 共21页
汇编语言程序例 - USTC.doc_第4页
第4页 / 共21页
汇编语言程序例 - USTC.doc_第5页
第5页 / 共21页
亲,该文档总共21页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《汇编语言程序例 - USTC.doc》由会员分享,可在线阅读,更多相关《汇编语言程序例 - USTC.doc(21页珍藏版)》请在三一文库上搜索。

1、Error! No text of specified style in document.第1章 Windows汇编语言程序设计基础Windows汇编语言程序分为控制台编程和图形界面编程两种,控制台编程相对简单一些。为了由浅入深,本书从控制台编程开始讲解。读者总希望用最快的速度掌握书中的概貌,为此从一个最简单的程序开始。一些汇编语言语法也结合程序进行讲解,有些指令和语法用注解的方法说明。1.1 第一个完整的Windows汇编语言程序Windows汇编语言程序有自己的编程规范,它的编程规范比Visual C要简单得多,调试也很方便。更重要的是系统把重要的东西都呈现给读者,使读者更能掌握其中的本

2、质。用一条一条的汇编语言指令很难写出大程序,Windows汇编语言程序也是调用系统提供的API来写程序。因而,用Windows汇编语言同样可写出大程序。以下是一个最简单的Windows程序。;程序功能:显示一个信息框。;ex1.asm(e:masmbase);程序名;编译链接方法:;ml /c /coff ex1.asm;link /subsystem:console ex1.obj.386;指明指令集.model flat,stdcall;程序工作模式,flat为Windows程序使用的模式(代码和数据;使用同一个4GB段),stdcall为API调用时右边的参数先入栈option case

3、map:none;指明大小写敏感include windows.incinclude user32.incincludelib user32.libinclude kernel32.incincludelib kernel32.lib.data;数据段szCaptiondb抬头串,0szTextdbHello!,0.code;代码段start:invoke MessageBox,;显示信息框NULL,;父窗口句柄offset szText,;正文串的地址offset szCaption,;抬头串的地址MB_OK;按钮invoke ExitProcess,;终止一个进程NULL;退出代码ends

4、tart;指明程序入口点程序运行结果见图1-1。图 1-1说明:程序调用了两个Windows提供的API。invoke是汇编语言中的伪指令,该指令的使用方法见1.4节。1.2 编译、链接和运行1.2.1 创建编译链接环境(1)安装MASM615调试工具。(2)建立一个VAR.BAT文件,内容如下。echo offrem 请根据 Masm32 软件包的安装目录修改下面的 Masm32Dir 环境变量!set Masm32Dir=c:Masm32set include=%Masm32Dir%Include;c:Program FilesMicrosoft Visual StudioVC98Incl

5、ude;(本行应接在上行后)Program FilesMicrosoft Visual StudioVC98MFCInclude;(本行应接在上行后)%include%(本行应接在上行后)set lib=%Masm32Dir%lib;%lib%set w2k=%Masm32Dir%Inclusew2k;%Includew2k%set path=%Masm32Dir%Bin;%Masm32Dir%Include;%Masm32Dir%Includew2k;%Masm32Dir%lib;%Masm32Dir%;%PATH%(本行应接在上行后)set Masm32Dir=echo on编译链接程序前

6、,需要切换到命令提示符方式,并运行该文件(设置好环境),然后方可进行编译链接。1.2.2 编译链接和运行以下以编译链接ex1.asm为例:(1)编译。ML /Zi /c /Fl /coff ex1.asmML 参数说明(注意参数大小写):/Zi 加符号调试信息/c 连接前的编译/Fl F1file产生列表文件/coff 产生COFF格式目标文件编译的更多参数说明,可用命令 ML /?查阅。(2)链接。LINK /SUBSYSTEM:console ex1.obj 其中console指明是控制台编程,如果是Windows窗口编程,则将console改为Windows。(3)运行。在Windows

7、下双击ex1.exe或在DOS命令提示符下键入ex1回车。1.2.3 建立编译链接批命令文件可以把编译链接过程写成批命令文件,以减少键盘输入量。例如:MLEXE.BATML /Zi /c /Fl /coff %1.asmLINK /subsystem:console %1.objdel %1.objdir %1.*如果要编译链接ex1.asm,则只需输入:MLEXE ex1回车1.3 将Windows汇编语言程序反汇编后的程序原形将可执行程序用IDA反汇编工具反汇编后,程序的代码部分可直接使用,程序的其他部分稍作修改后,即可再编译链接成可执行程序。具体修改部分见程序尾的说明。;iex1.asm

8、,本程序为ex1.exe反汇编后的程序。;iex1.asm(e:masmbase);编译链接方法:;ml /c /coff iex1.asm;link /subsystem:Windows iex1.obj.386.model flat,stdcalloption casemap:none.datainclude windows.incinclude user32.incincludelib user32.libinclude kernel32.incincludelib kernel32.libCaptiondb 抬头串,0Textdb Hello!,0.codepublic startst

9、artproc nearpush0;uTypepushoffset Caption;抬头串pushoffset Text;Hello!push0;hWndcallMessageBoxApush0;uExitCodecallExitProcessstartendpend start说明:API调用时右边的参数先入栈。用反汇编工具IAD反汇编后,保留代码段不变,将数据段中的数据搬入代码段,将其余部分删除,再加入包含文件和程序中的前4条指令,即可再编译链接成可执行程序。将可执行文件反汇编成汇编语言程序,经过适当修改后,再编译链接成可执行文件,这是十分有意义的。1.4 invoke伪指令的使用格式、变

10、量及数据段data 和data?的区别1.4.1 invoke伪指令的使用格式invoke 伪指令的使用格式为:invoke 函数名,参数1,参数2.参数的个数不定,可以没有,也可以有多个。如果invoke与某个函数的参数个数不匹配(少或多),则编译时报错。如果参数个数少,则报错“error A2137:too few arguments to INVOKE”;如果参数个数多,则报错“error A2137:too many arguments to INVOKE”。1.4.2 变量1变量的命名规则变量由大写字母A,B,Z,小写字母a,b,z,数字0,1,2,9,下划线,符号、$和?组成,且变

11、量的第一个符号不能是数字。变量的长度不能超过240个字符,不能使用指令名关键字,在同一个作用域内不能重名。应该养成良好的命名习惯,如表1-1所示。表 1-1缩 写含 义缩 写含 义sz表示以0结尾的字符串(ASCIIZ)lp表示指针long pointh表示句柄handlelpsz表示指向ASCIIZ的指针b表示字节bytef表示浮点数floatw表示字wordst表示结构体structdw表示双字double word例如:hWin表示窗口句柄lpArray表示指向数组的指针szString以0结尾的字符串stWndClassWNDCLASS结构bNumber以字节定义的数dwNumber以

12、双字定义的数wNumber以字定义的数2全局变量全局变量的作用域为整个程序。在.data和.data?段内定义的变量为全局变量。全局变量的定义格式为:变量名 类型 初始值变量名 类型 重复数量 dup(初始值)例如:count dw 0array db 10 dup(0)3局部变量局部变量的作用域为一个程序内。局部变量的定义格式为:local 变量名1重复数量:类型,变量名2重复数量:类型.局部变量要放在子程序的开始位置,并且没有初始值。例如:.386.model flat, stdcalloption casemap :noneincludewindows.incincludekernel3

13、2.incincludelibkernel32.lib.codeSubProcproc,x:byte,y:bytelocal a:byte;定义局部变量local b:byte;定义局部变量mov al,xmov a,almov al,ymov b,alretSubProc endpmainprocinvoke SubProc,1,2;调用子程序(右边参数先入栈)invoke ExitProcess,0;退出进程main endpend main4局部变量在栈中的位置将以上程序用IDA反汇编后的程序如下:sub_401000proc nearvar_2= byte ptr -2var_1= b

14、yte ptr -1arg_0= byte ptr 8arg_4= byte ptr 0Chpushebpmovebp, espaddesp, 0FFFFFFFCh;(-4)的补码=0FFFFFFFChmoval, ebp+arg_0;x=1movebp+var_1, almoval, ebp+arg_4;y=2movebp+var_2, alleaveretn8;将入口参数(x,y)退栈sub_401000endppublic startstartproc nearpush2push1callsub_401000push0call$+5jmpds:ExitProcessstartendp说明

15、:参数在栈中的位置见图1-2。图1-2 栈区示意图1.4.3 数据段data和data?的区别程序的一般结构为:.data定义变量并初始化(有初始值).data?定义变量(变量的初始值为?).const定义常量.code定义在.data?段中的变量的初始值只能是?。定义在.data?段中的变量不占用磁盘空间,即不增加.exe文件的大小。这是用.data?段的优点。例如,在.data?中定义变量:.data?sumdw?array 10 db dup(?)在实际应用中,上述变量的初始值为0。汇编语言中的类型如表1-2所示。表 1-2缩 写全 名 写 法名称和字节数dbbyte字节(1字节)dww

16、ord字(2字节)dddword双字(4字节)dffword三字(6字节)dqqword四字(8字节)dttbyte10字节BCD码sbyte有符号字节(1字节)sword有符号字(2字节)sdword有符号双字(4字节)real4单精度实型数(4字节)real8双精度实型数(8字节)real1010字节实型数(10字节)1.4.4 高级语法while-endw的使用 while-endw的格式为:.while(条件) 偱环体(条件满足时执行).endw;ex2.asm(e:masmbase) 高级语法while-endw的使用示例。;程序功能:用while偱环给字节数组赋值并计算。 .386

17、 .model flat, stdcall option casemap :none includewindows.inc includekernel32.inc includelibkernel32.lib includeuser32.inc includelibuser32.lib .data a db 10 dup(0);定义字节数组 buffer db 10 dup(0) CapMsgdb输出,0 szFmt db结果是:%d,0 i db0 sumdb0 .code start: mov edi,0 .while(i10) mov al,i mov aedi,al inc i inc

18、 edi .endw mov i,0 mov edi,0 .while(i=10) mov i,0 mov edi,0 .repeat mov eax,aedi add sum,eax inc i add edi,4 .until (i=10) mov eax,sum invoke wsprintf,;格式化信息串addr buffer,;信息串格式化后的存放地addr szFmt,;信息串的格式:结果是:%d,0 eax;二进制数invoke MessageBox,;显示信息框NULL,;父窗口句柄offset buffer,;正文串 结果是:%d,0 offset CapMsg,;抬头串

19、输出,0MB_OK;按钮确定 INVOKE ExitProcess,0;结束进程 endstart运行结果见图1-3。1.4.6 高级语法if-elseif-endif的使用if-elseif-endif的格式为:.if 条件1 指令(条件1满足时执行).elseif 条件2 指令(条件2满足时执行) .elseif 条件3 指令(条件3满足时执行) M endif;ex4.asm(e:masmbase) 高级语法if-elseif-endif的使用。;程序功能:输出number是正数或number是负数。 .386 .model flat, stdcall option casemap :n

20、one includewindows.inc includekernel32.inc includelibkernel32.lib includeuser32.inc includelibuser32.lib .data CapMsg db输出,0 szFmt dbnumber是正数:%d,0 szFmt2 dbnumber是负数:%d,0 number dd-9 buffer db 80 dup(0) .code start: mov eax,number invoke wsprintf,;格式化信息串addr buffer,;信息串格式化后的存放地addr szFmt,;number是正数

21、,0eax;二进制数mov eax,number.if eax = -9 invoke wsprintf,;格式化信息串 addr buffer, ;信息串格式化后的存放地 addr szFmt2, ;number是负数,0 eax ;二进制数.endifinvoke MessageBox,;显示信息框NULL,;父窗口句柄offset buffer,;正文串 结果是:%d,0 offset CapMsg,;抬头串 输出,0MB_OK;按钮确定 INVOKE ExitProcess,0; 结束进程 endstart运行结果见图1-4。图 1-41.4.7 条件运算符汇编语言中的条件运算符和高级

22、语言的条件运算符类似,这给编写程序带来了极大的方便。条件运算符如表1-3所示。表 1-3条件运算符功 能说 明=等于变量和操作数之间的比较!=不等于变量和操作数之间的比较大于变量和操作数之间的比较=大于等于变量和操作数之间的比较&逻辑与两个表达式的结果|逻辑或两个表达式的结果&按位与变量和操作数的结果!取反变量或表达式的结果条件运算时,非零为真,零为假。条件运算时,要注意表达式的左边应为寄存器或变量,不能为常数,表达式两边可以同时为寄存器,但不能同时为变量。标志测试伪指令: CARRY?表示进位标志是置位ZERO?表示零标志是置位SIGN?表示符号标志是置位PARITY?表示奇偶标志是置位OV

23、ERFLOW?表示溢出标志是置位;ex5.asm(e:masmbase) 条件运算符的使用。 .386 .model flat, stdcall option casemap :none includewindows.inc includekernel32.inc includelibkernel32.lib includeuser32.inc includelibuser32.lib .data CapMsg db输出,0 szFmt dbeax=%d(eax=1满足), ebx=%d(置进位标志), edx=%d(edx为零满足),0 buffer db 80 dup(0) .codest

24、art:mov eax,1.if eax=1 mov eax,2.endifmov ebx,10stc;置进位标志.if CARRY?;进位标志是置位? mov ebx,20 .endif xor edx,edx;使零标志置位(为1) .if !ZERO?;零标志不是置位? mov edx,8 .endif invoke wsprintf,;格式化信息串addr buffer,;信息串格式化后的存放地addr szFmt,;格式化串eax,;数ebx,edxinvoke MessageBox,;显示信息框NULL,;父窗口句柄offset buffer,;正文串offset CapMsg,;抬

25、头串 输出,0MB_OK;按钮确定 INVOKE ExitProcess,0;结束进程 endstart运行结果见图1-5。图 1-51.4.8 高级语法 continue的使用continue用在偱环while-endw和repeat-until中,它的功能是结束本次偱环(continue语句后的语句不执行),进入下一次偱环。continue的语法为:.continue;ex6.asm (e:masmbase)高级语法 continue 的使用。;程序功能:计算1+3+5+.+99的和。 .386 .model flat, stdcall option casemap :none inclu

26、dewindows.inc includekernel32.inc includelibkernel32.lib includeuser32.inc includelibuser32.lib .data array dw 100 dup(0);定义字数组 buffer db 80 dup(0) CapMsgdb输出,0 szFmt db结果是:%d,0 i dw1 sumdd0 .code start: mov edi,0 .while(i=100) mov ax,i mov arrayedi,ax;给数组赋值 inc i;计数 add edi,2;指向下一个 .endw mov i,1 mo

27、v edi,0 .while(i=100) movzx eax,word ptr arrayedi inc i;计数 add edi,2;指向下一个 mov edx,eax ror edx,1;偱环右移一位 .if !CARRY?;进位标志没有置位?(eax是偶数) .continue;结束本次偱环(此语句后的语句不执行) .endif add sum,eax;奇数求和 .endw invoke wsprintf,;格式化信息串addr buffer,;信息串格式化后的存放地addr szFmt,;信息串的格式:结果是:%d,0 sum;二进制数invoke MessageBox,;显示信息框

28、NULL,;父窗口句柄offset buffer,;正文串 结果是:%d,0 offset CapMsg,;抬头串 输出,0MB_OK;按钮确定 INVOKE ExitProcess,0;结束进程 endstart运行结果见图1-6。图 1-61.4.9 高级语法break if的使用break if语句用在偱环while-endw和repeat-until中,其功能是退出偱环。break if 语句的语法是:.break .if退出条件;ex7.asm(e:masmbase) 高级语法 break if 的使用。;程序功能:计算1+2+3+.+50的和。 .386 .model flat,

29、stdcall option casemap :none includewindows.inc includekernel32.inc includelibkernel32.lib includeuser32.inc includelibuser32.lib .data array dw 100 dup(0);定义字数组 buffer db 80 dup(0) CapMsgdb输出,0 szFmt db结果是:%d,0 i dw1 sumdd0 .code start: mov edi,0 .while(i=100) mov ax,i mov arrayedi,ax;给数组赋值 inc i;计

30、数 add edi,2;指向下一个 .endw mov i,1 mov edi,0 .while(i=100) movzx eax,word ptr arrayedi .break .if eax=51 add sum,eax;求和 inc i;计数 add edi,2;指向下一个 .endw invoke wsprintf,;格式化信息串addr buffer,;信息串格式化后的存放地addr szFmt,;信息串的格式:结果是:%d,0 sum;二进制数invoke MessageBox,;显示信息框NULL,;父窗口句柄offset buffer,;正文串 结果是:%d,0 offset

31、 CapMsg,;抬头串 输出,0MB_OK;按钮确定 INVOKE ExitProcess,0;结束进程 endstart运行结果见图1-7。图 1-71.4.10 结构体汇编语言中的结构体和共用体与C语言中的基本类似。结构体的定义格式如下:名字 struct成员列表名字 ends例如(windows.inc文件中包含以下结构):COORD STRUCTx WORD ?y WORD ?COORD ENDSSYSTEMTIME STRUCT WYearWORD ?;年(4位) WMonthWORD ?;月(112) WDayOfWeekWORD ?;星期(06) 0=星期天,1=星期一. wD

32、ayWORD ?;日(131) wHourWORD ?;时(023) wMinuteWORD ?;分(059) wSecondWORD ?;秒(059) wMillisecondsWORD ?;毫秒(0999)SYSTEMTIME ENDS ;ex8.asm(e:masmbase) 结构体应用示例。.386 .model flat, stdcall option casemap :none includewindows.inc includekernel32.inc includelibkernel32.lib includeuser32.inc includelibuser32.lib .d

33、ata;COORD STRUCT;windows.inc 文件中有定义; x WORD ?; y WORD ?;COORD ENDS buffer db 80 dup(0) CapMsgdb输出,0 szFmt dbstPos.x 的和 = %d, stPos.y 的和 = %d,0 stPos1 COORD ;定义结构体变量并初始化 stPos2 COORD ;定义结构体变量(取结构体原初始值) stPos3 COORD 2,4;定义结构体变量并初始化 stPos4 COORD ,40;定义结构体变量并初始化 stPos COORD 10 dup();定义结构体数组 .code start:

34、 mov stPos2.x, 10;域的使用 mov stPos2.y, 20 mov ecx,10 mov edi,offset stPos;edi指向结构体变量mov eax,1mov ebx,11: mov (COORD ptredi).x, ax mov (COORD ptredi).y, bx add edi,type COORD;结构体的大小 inc ax inc bx loop short B xor eax,eax xor ebx,ebx mov ecx,10 mov edi,offset stPos;edi指向结构体变量:add ax,(COORD ptredi).xadd

35、bx,(COORD ptredi).yadd edi,type COORD;结构体的大小 loop short B invoke wsprintf,;格式化信息串addr buffer,;信息串格式化后的存放地addr szFmt,;信息串的格式eax,ebxinvoke MessageBox,;显示信息框NULL,;父窗口句柄offset buffer,;正文串 offset CapMsg,;抬头串MB_OK;按钮确定 INVOKE ExitProcess,0;结束进程endstart运行结果见图1-8。图 1-8;ex9.asm(e:masmbase) 显示系统时间。.386 .model

36、 flat, stdcall option casemap :none includewindows.inc includekernel32.inc includelibkernel32.lib includeuser32.inc includelibuser32.lib .datasysTimeSYSTEMTIME ;定义结构体变量(结构体由系统定义)CapMsg db系统当前时间,0szFmt db%d年%2d月%2d日,0Dh,0Ah,0Dh,0Ahdb%2d:%2d:%2d,0buffer db 80 dup(0) .codestart:invoke GetLocalTime,offset sysTime;获取系统时间(从结构体返回)movzx esi,sysTime.wYear ;年(4位)movzx edi,sysTime.wMonth;月(112)movzx edx,sysTime.wDay;日(131)movzx eax,sysTime.wHou

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

当前位置:首页 > 科普知识


经营许可证编号:宁ICP备18001539号-1