您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 其它行业文档 > 汇编语言 第十章 Windows汇编程序设计基础
汇编语言程序设计第十章Windows汇编语言程序设计基础10.1Windows汇编环境10.2Windows下的子程序设计与函数调用10.3使用VC编译调试汇编程序10.1Windows汇编环境10.1.1Windows下的MASM与LINK10.1.2Windows汇编源程序的格式10.1.1Windows下的MASM与LINKMASM汇编器LINK连接器汇编连接步骤1.MASM汇编器MASM汇编器的命令行用法为:ml[/选项]汇编程序源文件[/link链接选项]选项功能/c仅进行编译,不自动进行链接/coff产生的obj文件格式为COFF格式/Cp源程序中区分大小写/Fofilename指定输出的obj文件名/Fl[filename]产生.lst列表文件/Ipathname指定include文件的路径/link指定链接时使用的选项2.LINK链接器LINK编译器的命令行用法为:link[选项][文件列表]选项功能/out:输出文件名输出的文件名,扩展名默认为.exe/map:文件名生成MAP文件/libpath:目录名指定库文件的目录路径/implib:文件名指定导入库文件/entry:标号指定入口/comment:字符串在PE文件的文件头后面加上文本注释(版权信息)/stack:数字设定堆栈的大小/subsystem:系统名指定程序运行的环境,可以是以下几种之一:Native,Windows,Console,Windowsce,Posix以一个源程序文件hello.asm为例,对它进行汇编链接,最后运行。用MASM汇编一个程序的方法为ml/c/coffhello.asm用LINK链接生成可执行文件的方法为:link/subsystem:consolehello.obj可以简化为:ml/coffhello.asm/link/subsystem:console3.汇编链接步骤10.1.2Windows汇编源程序的格式hello.asm例子程序格式一个Windows界面的汇编程序1.一个显示字符串的汇编程序举例hello.asm(教材P311)等同于下面的C程序#includestdio.hintmain(){printf(HelloWorld!\n);return0;}2.程序格式(1)模式定义程序的第一部分是有关模式定义的3条语句:.386.modelflat,stdcalloptioncasemap:none这些语句定义了程序使用的指令集、工作模式。①指令集.386语句是汇编语言的伪指令,说明使用的指令集是哪一种CPU的。如果用汇编语言编写的是驱动程序或者驱动程序的一个小模块,而且驱动程序在特权级0上运行,就需要使用.386p,后面带p的伪指令表示程序中可以使用特权指令。在编程中如果使用了MMX指令,除了定义.586之外,还要加上一句.mmx伪指令:.586.mmx②工作模式.model语句用来定义程序工作的模式,它的格式是:.model内存模式[,调用规则][,其他模式]在DOS的可执行程序中,可用到.com文件和.exe文件。在Windows环境下,可执行程序只有一种内存模式,即Flat(平坦)模式。②工作模式(续)在DOS下的汇编语言程序中,常常有这样的程序片段:MOVAX,DATAMOVDS,AX其作用是给数据段寄存器DS赋值。在编程时,必须考虑这些DS,ES,SS等段寄存器是否正确设置。在Windows汇编语言程序中,则不必考虑这些问题。在程序中,不需要也不应该给CS,DS,ES,SS等段寄存器赋值。③option语句option语句有许多选项,这里介绍一种:optioncasemap:none这条语句说明程序中的变量和子程序名是否对大小写敏感。由于WindowsAPI函数中的函数名称是区分大小写的,所以应该指定这个选项“casemap:none”(2)includelib语句汇编程序中也需要调用一些外部模块(子程序/函数)来完成部分功能。例如:使用下面语句通知链接程序使用msvcrt.libincludelibmsvcrt.lib若要使用使用其他库文件,只需重复编写Includelib库文件名(3)函数声明语句格式:函数名称PROTO[调用规则]:[第一个参数类型][,:后续参数类型](4)include语句语法:include文件名例如:includekernel32.incincludeuser32.inc以后程序中用到user32.dll和kernel32.dll中的函数时,不需要事先声明就可以直接使用。(5)数据和代码部分程序中的数据部分和代码部分是分开定义的,分别以.data和.code开始,以end结束。end语句一般是整个程序的最后一条语句,end语句后面跟的是起始标号,指出了程序执行的第一条指令的位置。(6)跨行的语句当源程序的某一语句过长,不利于书写和阅读时,可以用反斜杠(\)作为换行符,将这条语句分为几行来写。3.一个Windows界面的汇编程序下面给出一个使用Windows图形界面的汇编源程序(教材P319)。hellow2.asm(显示一个Windows消息框)在编译链接时,必须在subsystem选项中指定“windows”,而不是“console”。命令为:ml/coffhellow.asm/link/subsystem:windows运行结果:1.GUI程序2.CUI程序10.1.3图形界面与字符界面10.2Windows下的子程序设计与函数调用10.2.1通过全局变量及寄存器传递参数10.2.2C函数的参数传递方式cdecl10.2.3伪指令invoke10.2.4Windows中汇编与C的相互调用10.2.5在汇编中调用Windows的API10.2.6C++与汇编高级语言的函数就是汇编语言的子程序。汇编语言传递参数有3种常用方法:(1)通过寄存器传递;(2)通过数据区内的变量来传递;(3)通过堆栈传递。10.2.1通过全局变量及寄存器传递参数在程序中设计了两个子程序:AddProc1子程序使用ESI和EDI作为入口参数,做完加法后把和放在EAX中;AddProc2子程序使用A和B作为入口参数,做完加法后把和放在R中。程序:callret.asm(教材P321)结果:10+20=3050+60=110CALL指令执行时,它首先把返回地址作为一个双字压栈,再进入子程序执行。子程序最后执行的RET指令从堆栈中取出返回地址,返回到主程序。CALL指令和RET指令执行是必须依赖于堆栈的。cdecl方式是C语言函数的默认方式调用规则:(1)使用堆栈传递参数。(2)主程序按从右向左的顺序将参数逐个压栈,(3)在子程序中,使用[EBP+X]的方式来访问参数。(4)子程序用RET指令返回。(5)由主程序执行“ADDESP,n”指令调整ESP,达到堆栈平衡。(6)子程序的返回值放在EAX中。10.2.2C函数的参数传递方式cdecl使用invoke伪指令对主程序和子程序的简化。在调用子程序时,使用invoke伪指令,后面跟子程序名和各个参数的取值即可。10.2.3伪指令invoke(1)子程序的调用规则(2)子程序的参数(3)子程序的进入/退出代码(4)子程序的返回指令(5)主程序中采用invoke语句程序示例:invoke.asm(P327)机器指令列表:invoke21.使用invoke伪指令注意事项invoke伪指令(续)对照invoke.asm和机器指令列表,可以观察到以下几点:(1)自动加入的指令AddProc5,AddProc6中的一些语句是MASM自动加入的(2)参数的替换参数a用[EBP+8]替换,参数b用[EBP+12]替换。(3)返回指令AddProc5采用C规则,用“RET”返回;AddProc6采用stdcall规则,用“RET8”返回invoke伪指令(续)(4)invoke语句转换为CALL指令invoke后面跟的参数被逐一压入堆栈,再跟上一条CALL指令。(5)堆栈平衡对AddProc5的调用,在CALL指令后面用“ADDESP,8”来平衡堆栈。对AddProc6的调用,由于在返回时使用了“RET8”,在CALL指令后面不需要“ADDESP,8”invoke伪指令(续)2.使用invoke调用子程序的一些限制invoke伪指令后面跟的参数必须直接能够作为PUSH指令的源操作数。错误的写法:invokeaddproc,r*2,30正确的写法:MOVEBX,rSHLEBX,1invokeaddproc,EBX,3010.2.4Windows中汇编与C的相互调用关键:两种语言的接口问题解决方法:在C程序中直接嵌入汇编代码由C语言主程序调用汇编子程序1.直接嵌入C语言程序中直接嵌入汇编语句格式为:_asm汇编语句对于连续的多个汇编语句,格式为:asm{汇编语句汇编语句…}10.2.4.1直接嵌入内嵌汇编语句的操作码必须是有效的80x86指令。不能使用byte,word,dword等语句定义数据。内嵌汇编语句中的操作数可以是:–寄存器;–局部变量、全局变量和函数参数;–结构成员。程序清单:inline.c(P328)2.C模块调用汇编模块C源程序中所有语句要符合C的语法规则;汇编源程序的所有语句要符合汇编的语法规则;C模块可调用汇编模块中的子程序,还可以使用汇编模块中定义的全局变量;汇编模块可调用C模块中的函数,可以使用C模块中定义的全局变量。C模块使用汇编模块中的变量C和汇编有些变量类型是等价的,可以相互转换:C源程序要使用汇编模块中的变量,则在汇编模块中的变量名必须以下划线开头。例如:_strFormulasbytePythagoreantheorem:x*x+y*y=z*z,0_xvalsdword3_yvalsdword4_zvalsdword5C模块中使用这些变量时,前面的下划线必须去掉。汇编模块使用C模块中的变量C模块中,应采用extern来指明变量可以由外部模块所使用,例如:externintx,y,z;在汇编模块中,要使用这个变量,应该用EXTRN加以说明,例如:EXTRN_x:sdword,_y:sdword,_z:sdword使用变量如:MOVEAX,_xC模块调用汇编模块中的子程序关键功能用汇编语言来编写,再由C语言来调用。程序举例:C/汇编联合编程的主模块united.c(P330)C/汇编联合编程的子模块unite.asm例如,要编写一个显示当前时间的汇编程序,有两个API可以调用:_CRTIMPtime_t__cdecltime(time_t*);_CRTIMPchar*__cdeclctime(consttime_t*);而time_t就是一个长整型数。typedeflongtime_t;/*timevalue*/例9.编写显示当前时间的C程序(见教材p335)。10.2.5在汇编中调用Windows的API10.2.6C++与汇编1.使用C方式共享变量和函数在C++一方,要将与汇编模块共享的变量、函数等用extern“C”的形式说明。举例:C++/汇编联合编程ArraySum.cpp(P338)C++/汇编联合编程ArraySum.asm2.C++类的实例与方法程序demo.cpp(P341)中,有两个类A,B。A是B的基类,类A和类B各有自己的reset()方法和output()方法。程序的输出结果为:A:1B:2,3A:10B:10,0类A的实例a,类B的实例b所占用的内存单元的内容如图:类的vtable就像一张表格,存放它的虚函数的地址。10.3使用VC编译调试汇编程序10.3.1建立工程10.3.2设置调试选项10.3.3常用调试命令10.3.1建立工程(1)启动VC后,从菜单中选择File→New。(2)在打开的New对话框顶部,单击Projects,再选中Win32ConsoleApplication。在Location编辑框中输入“c:\asm”,再在Projectname中输入test。(3)
本文标题:汇编语言 第十章 Windows汇编程序设计基础
链接地址:https://www.777doc.com/doc-3973814 .html