




已阅读5页,还剩52页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
WINDOWS 环境下32 位汇编语言程序设计,1 编程环境,编辑工具:记事本、UltraEdit32、EditPlus等汇编程序: ML.EXE (Masm and Link) 6.11 版本及以上 连接程序:Link.EXE调试工具:TD32.exe资源编译器:RC.EXE, CVTRES.EXE常用的API函数申明及引入库,从汇编网站上下载: WIN32编程环境(不需安装)使用“80X86汇编语言程序设计”作为教材的学生,在编写WIN32程序时建议下载此版本的开发环境。它是MASM 6.14(MASM32v5)。,2 几个简单的例子,.386.model flat, stdcall option casemap:none include masm32v5includewindows.inc Include masm32v5includekernel32.inc include masm32v5includeuser32.inc includelib masm32v5libkernel32.lib includelib masm32v5libuser32.lib .data MsgBoxCaption db “ win32 example ,0 MsgBoxText db “ Win32 Assembly is Great! ,0 .code start: invoke MessageBox, NULL, addr MsgBoxText, addr MsgBoxCaption, MB_OK invoke ExitProcess, NULL end start,显示一个对话框DEMO32.asm,编译: e:masm32v5bin ml /c /coff demo32.asm注意:直接运行 ml , 会给出提示,包括其版本和得到帮助的方法。 e:masm32v5bin ml /help 可以显示所有的编译参数。,连接: e:masm32v5bin link /subsystem:windows demo32.obj注意:直接运行 link , 会给出连接参数提示。,/c : 只编译,不连接; /coff 产生COFF格式的文件/subsystem:windows 产生windows下的程序,对 demo32.asm 的改进现存问题分析: (1) 源文件中包含的头文件和引入库都带有路径 路径发生变化,怎么办? (2) 编译、连接时都要输入长串,使用不方便 (3) 原文件及其生成文件与bin目录放在一起, 管理不方便,改进: (1) 删除源文件中的相关路径 (2) 建立新目录 (3) 建立批处理文件,编译、连接的方法之三 使用 QEDITOR.EXE,QEDITOR 将编辑、汇编、连接等组装在一起。其组装方法是通过一个文本文件来说明其菜单项及调用的程序。 参见:QEDITOR.INI MENUS.INI,编译、连接的方法之四 写一个工程文件,说明需要汇编、连接的程序,以及相关的编译参数。, 存储模型说明伪指令MODEL 格式: .MODEL 存储模型 ,语言类型 ,系统类型,堆栈选项 功能:用于指定程序中各个段的属性、程序的运行环境,调用规则。,段的简化定义 用简单的方式定义代码段、数据段、堆栈段等。,3 宏汇编语言对WIN32编程的支持,格式: .MODEL 存储模型 ,语言类型 ,系统类型,堆栈选项,语言类型:指定了函数命名、调用和返回的方法。语言类型取值:C、PASCAL或STDCALL等。 根据WIN32中API的要求,应选择STDCALL。采用堆栈法传递参数,参数进栈次序为:函数原型描述的参数中最右边的参数最先入栈、最左边的最后入栈;由被调用者在返回时清除参数占用的堆栈空间。注意:省略语言类型时则应在函数说明/定义语句PROTO、PROC等中说明。,格式: .MODEL 存储模型 ,语言类型 ,系统类型,堆栈选项,堆栈选项:NEARSTACK (SS=DS) FARSTACK (SSDS) 省略时为NEARSTACK。,系统类型:目前只有OS_DOS选项,可省略。,存储模型说明伪指令必须放在源文件中所有其它段定义伪指令之前且只能使用一次, 定义代码段伪指令 格式:.CODE 段名 功能:说明一个代码段的开始,同时也表示上一个段的结束。 如果指定了段名,则该段就以此名字命名。 否则,在TINY、SMALL、COMPACT和FLAT模式时,段名为“_TEXT”; 在MEDIUM、LARGE和HUGE模式时,段名为“模块名_TEXT”。,定义数据段伪指令格式:.DATA 或 .DATA? 功能:说明一个数据段的开始,同时也表示上一 个段的结束。 当采用.DATA定义数据段时,段内的变量是经过初始化的,都会占用执行文件的磁盘存储空间(即使变量的初始值为?);其段名被指定为_DATA。 当采用.DATA?定义数据段时,段内的变量是未初始化的,可以减少执行文件的磁盘存储空间并能增强与其它语言的兼容性;其段名被指定为_BSS。,源程序中每一个段定义都不再需要单独的段结束伪指令,但源程序的最后仍需要用END伪指令结束。,堆栈段定义:.STACK 堆栈字节数 字节数的缺省值是1024,常数(只读)数据段定义:.CONST,程序开始伪指令:.STARTUP,特别说明:,对于DOS下的16位段程序,也可以使用简化段定义。只是要先写 .MODEL SMALL 再写 .386 仍然使用DOS下的汇编和连接程序。程序示例: c6_242_1.asm (段的简化定义) c6_242_2.asm (用了 .STARTUP),.model small.386.STACK 200.DATAINPUT DB Please input x (0.9) : $.CODE.startup MOV DX, OFFSET INPUT MOV AH, 9 INT 21H MOV AH ,1 INT 21H CMP AL, 0 ; 判断输入是否合法 JB LERR EXIT: MOV AH, 4CH INT 21H END,DS,SS,SP,DS,SP,SS,特别说明:,对于 Windows下的32位段程序,可以用如下说明: .386 .model flat, stdcall,系统会自动的将 .DATA段,.DATA?段,.CONST段,.STACK段组合成一个组 DGROUP。 自动的将 DS,ES,SS设置成组DGROUP的段址。,子程序的说明、定义及调用:通过伪指令PUBLIC、EXTRN、PROC和指令CALL等完成。,(2) 原型说明与函数调用,3 宏汇编语言对WIN32编程的支持,问题:当子程序的参数较多或与高级语言混合编程时,主、子程序之间的参数传递复杂,容易出错,程序的可读性也较差。,新方法:原型说明伪指令PROTO 调用伪指令INVOKE 与高级语言的原型说明和调用类似。以下也将子程序称作过程或函数。,函数类型:可以是NEAR、FAR,NEAR16、NEAR32、FAR16和FAR32中的一种。WIN32应用程序中一般为NEAR类型。如果不指定的话,将由汇编程序根据 .MODEL指定的内存管理模式进行判断选择。, 原型说明伪指令PROTO,格式:函数名 PROTO 函数类型 语言类型 参数名:参数类型,.功能:用于说明本模块中要调用的过程或函数。,语言类型:指明参数传递的方式采用哪种语言的规定(C、PASCAL或STDCALL等).如果在.MODEL后指定了语言类型,此处可省略。,参数说明:每个参数项由参数名和参数类型组成。由于参数名仅用于增加程序的可读性,可以省略,但冒号和参数类型不能省略。,MessageBoxA PROTO hWnd:DWORD, lpText:DWORD, lpCaption :DWORD,uType:DWORD函数类型语言类型均省略,有4个参数。 hWnd为双字类型,是消息框所属的窗口的地址。 为0时表示没有所属窗口;lpText是在框中待显示字符串的首地址指针;lpCaption是在该消息框标题处待显示字符串的首 地址指针,为0时显示标题“Error”;uType是指定消息框所带图标和按钮的样式 (详细功能请参见6.4.3节中的消息处理函数)该函数的原型说明在头文件user32.inc中,原型说明示例:,PROTO的功能类似于EXTRN但表达能力更强。建议在说明外部函数的时候全部改用PROTO,完整的函数定义伪指令PROC,格式:函数名 PROC 函数类型语言类型 USES 寄存器表,参数名:类型.功能:定义一个新的函数(函数体应紧跟其后),函数类型、语言类型和各参数应与对应的PROTO说明一致 参数名是用来传递数据的,可以在程序中直接引用,故不能省略对16位段,当类型为字时,:WORD 可以省略对32位段,当类型为双字时,:DWORD 可省略USES后的寄存器是需要在子程序中入栈保护 (由汇编程序自动加入入栈保护和出栈恢复的指令语句),紧跟在PROC语句之后,用LOCAL伪指令说明。在宏定义中使用LOCAL说明局部标号和变量时,是为了避免符号名的重复定义,而这里主要是定义函数内的临时局部变量。一般格式为: LOCAL 变量名 数量 :类型数量:用于说明重复单元的数目,类似DUP。,局部变量定义:,局部变量所指的单元在堆栈中,它们的位置一般放在 PUSH EBP/BP 保存的 EBP/BP 数值的后面。,局部变量的空间分配:,RADIX_S PROC NEAR STDCALL USES EBX EDX SI, LpResult, Radix:DWORD, NUM:DWORDLOCAL COUNT:WORD,设想在调用该函数时,其堆栈空间的状态?,NUM,Radix,LpResult,(IP),(BP),COUNT,(EBX),(EDX),(SI),RADIX_S PROC NEAR STDCALL USES EBX EDX SI, LpResult, Radix:DWORD, NUM:DWORDLOCAL COUNT:WORD,对比 4.5.6小节示例3,P139用堆栈传递参数。,观察数据压入堆栈的次序请同学们用VC观察函数调用时的空间状态。,在后续的指令语句中可以直接引用局部变量的名字,但此时的寻址方式是使用EBP/BP的变址方式。,局部变量所指的单元在堆栈中,它们的位置一般放在 PUSH EBP/BP 保存的 EBP/BP 数值的后面。,局部变量的空间分配,观察 P245, 比较使用完整的PROC语句和LOCAL后,对原来的子程序的简化。,观察 P245, 比较使用完整的PROC语句和LOCAL后,对原来的子程序的简化。RADIX_S PROCPUSH BPMOV BP,SPSUB SP,2PUSH EBXPUSH EDXPUSH SIMOV WORD PTRBP-2,0MOV EAX,10BPMOV SI,4BPMOV EBX,6BP, MOV AX,SIPOP SIPOP EDXPOP EBXMOV SP,BPPOP BPRET 10RADIX_S ENDP,例如:INVOKE RADIX_S,SI,10,EAX EAX处在NUM参数的位置(待转换的数); 数值10处在Radix参数的位置(基数); SI处在LpResult参数的位置,转换结果存放缓冲区的首址应预先送到SI中。, 函数调用伪指令INVOKE,格式:INVOKE 函数名 ,参数.功能:调用由完整的函数定义伪指令PROC定义 的函数。其中,参数可以是各种表达式。,INVOKE与CALL都完成了子程序的调用,它们的差别在什么地方?,取地址伪指令 ADDR,例如:INVOKE RADIX_S,ADDR BUFA,10,EAX ADDR BUFA也可用OFFSET BUFA代替。 ADDR与OFFSET的相同点: 均可以取得变量和标号的偏移地址值。不同点: ADDR只能用在INVOKE语句中; ADDR后面的符号名必须在此语句之前已定义; ADDR可以处理局部变量而OFFSET 则不能(因局部变量是在运行时才在堆栈中分配内存空间)。,“结构”是用户自定义的复合数据类型,它将各种不同类型的数据组织到一个数据结构中,以方便处理复杂的数据项。在描述结构型数据或使用结构型变量之前,需要先对用到的结构类型进行说明。,(3) 结构,结构定义格式结构名 STRUCT 数据定义语句序列结构名 ENDS,注:较低版本的汇编程序使用STRUC,COURSE STRUCT CID DD ? ;课程编号 CTITLE DB 20 DUP(0);课程名 CHOUR DB 0 ;学时数 CTEACHER DB WANG ZHONGLING ;主讲教师 CTERM DB 1,2 ;开课学期COURSE ENDS,变量名 结构名 变量名是当前定义的结构变量的名称,可以省略。结构名是在前面说明结构类型时自定义的名字。,结构变量定义的一般格式,注: 结构变量一般放在数据段中,而结构说明应放在结构变量定义之前,不属于任何段。,C1 COURSE ;5个字段均用结构说明 时给的初值C2 COURSE ;仅CTERM字段未重新赋值 COURSE ;CTEACHER和CTERM字段未重新赋值, ;省略了变量名C4 COURSE 5 DUP() ;定义了5个相同的结构变量, ;对CID、CHOUR重新赋了值 COURSE 10 DUP() ;定义了10个结构变量, ;即预留了相应的存储空间,例MOV EAX,C2.CID ;2102MOV AL,C2.CTITLE;SMOV AH,C2.CTITLE+2;UMOV C2.CTERM+1,3; 2 改为 3C2 COURSE ,COURSE STRUCT CID DD ? ;课程编号 CTITLE DB 20 DUP(0);课程名 CHOUR DB 0 ;学时数 CTEACHER DB WANG ZHONGLING ;主讲教师 CTERM DB 1,2 ;开课学期COURSE ENDS,例MOV BX,OFFSET C2MOV EAX,BX.CID ;2102MOV AL,BX.CTITLE;SMOV AH,BX.CTITLE+2;UMOV BX.CTERM+1,3; 2 改为 3C2 COURSE ,COURSE STRUCT CID DD ? ;课程编号 CTITLE DB 20 DUP(0);课程名 CHOUR DB 0 ;学时数 CTEACHER DB WANG ZHONGLING ;主讲教师 CTERM DB 1,2 ;开课学期COURSE ENDS,6.4.2 WIN32程序的结构,Windows程序种类: 核心驱动程序 动态连接库 窗口应用程序 不同程序都有各自的标准框架。无论是采用何种编程语言,编程人员只需在规定的框架下增加自己需要的代码,即可得到符合Windows运行要求的程序。,基于窗口的应用程序结构: 主程序 窗口主程序 WinMain 窗口消息处理程序WndProc 用户处理程序 RADIX_S,得到本应用程序的句柄hInstance(GetModuleHandle),结束(ExitProcess),开始,当程序需要从命令行得到参数时,则需要获取命令行参数的地址CommandLine(GetCommandLine),调用窗口主程序(WinMain),主程序流程图,句柄是一个代号。 用来唯一标识某一个程序或窗口等,一般是它们的地址。 应用程序的句柄、窗口的句柄、图标的句柄、文件的句柄等。 用户程序必须先通过Windows API来获得指定程序或窗口的句柄,然后才能通过该句柄对所代表的程序或窗口进行操作,如发送消息等。,句柄是什么?,START: INVOKE GetModuleHandle,NULL MOV hInstance,EAX INVOKE GetCommandLine MOV CommandLine, EAX INVOKE InitCommonControls INVOKE WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT INVOKE ExitProcess,EAX,主程序示例:,N,Y,窗口参数初始化,注册窗口类(RegisterClassEx),WinMain,创建窗口类(CreateWindowEx),装载菜单等各种资源(可选),从操作系统获取与本窗口程序有关的消息(GetMessage),转换键盘消息(TranslateMessage),将消息分发到本程序的窗口消息处理过程(DispatchMessage),返回,窗口主程序流 程 图,是退出消息吗?,WinMain PROC hInst :DWORD, hPrevInst :DWORD, CmdLine :DWORD, CmdShow :DWORD LOCAL wc :WNDCLASSEX LOCAL msg :MSG invoke RegisterClassEx, ADDR wc ; 注册窗口 invoke CreateWindowEx,NULL, ; 创建窗口 ADDR szClassName, ADDR AppName, WS_OVERLAPPEDWINDOW + WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL,NULL, hInst, NULLStartLoop: invoke GetMessage,ADDR msg,NULL,0,0 cmp eax, 0 je ExitLoop invoke TranslateMessage, ADDR msg invoke DispatchMessage, ADDR msg jmp StartLoop ExitLoop: mov eax, msg.wParam retWinMain endp,调用相应的处理函数,返回,窗口过程WndProc,消息的缺省处理(DefWindowProc),返回 0,Y,N,窗口消息处理程序流 程 图,要处理该消息吗?,WndProc proc hWnd :DWORD, uMsg :DWORD, wParam :DWORD, lParam :DWORD .IF uMsg = WM_DESTROY INVOKE PostQuitMessage, NULL .ELSEIF uMsg = WM_COMMAND MOV EAX, wParam .if AX = IDM_TEST invoke MessageBox, NULL,ADDR Test_string, OFFSET AppName, MB_OK .elseif AX = IDM_HELLO .elseif AX = IDM_GOODBYE invoke MessageBox,NULL,ADDR Goodbye_string, OFFSET AppName,MB_OK .else INVOKE DestroyWindow,hWnd .ENDIF .ELSE INVOKE DefWindowProc,hWnd,uMsg,wParam,lParam RET .ENDIF XOR EAX, EAX RETWndProc ENDP,例: 在屏幕上创建一个窗口,窗口的标题为:“Our First Window”。当按下一个键时,在窗口中显示字符串“These words are printed in the window!”,并将该键的ASCII码以十六进制的形式显示出来。显示的格式为:,模块结构图,用户子程序 (Convert),窗口主程序(WinMain),窗口消息处理程序 (WndProc),主程序,源程序,1.头文件和数据段定义,5.窗口消息处理程序,6.用户处理程序,3.窗口主程序(1),4.窗口主程序(2),2.主程序,.386 ;e616c.asm.MODEL FLAT,STDCALL ;存储模型说明 e616c.asmOPTION CASEMAP :NONE ;区分大小写说明WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD ;原型说明WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORDConvert PROTO :BYTE, :DWORDINCLUDE windows.inc ;头文件说明INCLUDE gdi32.incINCLUDE user32.incINCLUDE kernel32.incINCLUDELIB gdi32.lib ;引入库说明INCLUDELIB user32.lib INCLUDELIB kernel32.lib.DATAClassName DB TryWinClass,0 ;窗口类名AppName DB Our First Window ,0 ;窗口标题hInstance DD 0 ;实例句柄CommandLine DD 0OurText DB These words are printed in the window! ;窗口中待显示的字符串num1 = $-OurTextOurStr DB The ASCII of char ? is:,20H ;20H为空格符szASCII DB 00H,20H,20H ;后面加了2个空格num2 = $-OurStr,返回,头文件和数据段定义,主程序,.CODESTART: INVOKE GetModuleHandle, NULL ;获得并保存本程序的句柄 MOV hInstance,EAX INVOKE GetCommandLine MOV CommandLine,EAX INVOKE WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT ;调用窗口主程序 INVOKE ExitProcess,EAX ;退出本程序,返Windows,返回,窗口主程序(1),WinMain PROChInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,CmdShow:DWORDLOCAL wc :WNDCLASSEX ;创建主窗口时所需要的信息由该结构说明LOCAL msg :MSG ;消息结构变量用于存放获取的消息LOCAL hwnd :HWND ;存放窗口句柄,给WNDCLASSEX结构变量wc的各字段赋值MOV wc.cbSize,SIZEOF WNDCLASSEX ;WNDCLASSE结构类型的字节数MOV wc.style, CS_HREDRAW or CS_VREDRAW ;窗口风格(当窗口高度和宽度变 ; 化时则重画窗口)MOV wc.lpfnWndProc, OFFSET WndProc ;本窗口过程的入口地址(偏移地址)MOV wc.cbClsExtra,NULL ;不使用自定义数据则不需OS预留空间,MOV wc.cbWndExtra,NULL ;同上PUSH hInst ;本应用程序句柄wc.hInstancePOP wc.hInstanceMOV wc.hbrBackground,COLOR_WINDOW+1 ;窗口的背景颜色为白色MOV wc.lpszMenuName,NULL ;窗口上不带菜单,置为NULLMOV wc.lpszClassName,OFFSET ClassName ;窗口类名TryWinClass的地址INVOKE LoadIcon,NULL,IDI_APPLICATION ;装入系统默认的图标MOV wc.hIcon,EAX ;保存图标的句柄 MOV wc.hIconSm,0 ;窗口不带小图标INVOKE LoadCursor,NULL,IDC_ARROW ;装入系统默认的光标 MOV wc.hCursor,EAX ;保存光标的句柄,返回,窗口主程序(2),INVOKE RegisterClassEx, ADDR wc ;注册窗口类 INVOKE CreateWindowEx,NULL,ADDR ClassName, ;建立“TryWinClass”类窗口 ADDR AppName, ;窗口标题Our First Window的地址 WS_OVERLAPPEDWINDOW+ WS_VISIBLE, ;创建可显示的窗口 CW_USEDEFAULT,CW_USEDEFAULT, ;窗口左上角坐标默认值 CW_USEDEFAULT,CW_USEDEFAULT, ;窗口宽度,高度默认值 NULL,NULL, ;无父窗口,无菜单 hInst,NULL ;本程序句柄,无参数传递给窗口 MOV hwnd,EAX ;保存窗口的句柄StartLoop: ;进入消息循环 INVOKE GetMessage, ADDR msg,NULL,0,0 ;从Windows获取消息 CMP EAX,0 ;如果(EAX)不为0 则要转换并分发消息 JE ExitLoop ;如果(EAX)为0 则转ExitLoop INVOKE TranslateMessage, ADDR msg ;从键盘接受按键并转换为消息 INVOKE DispatchMessage, ADDR msg ;将消息分发到窗口的消息处理程序 JMP StartLoop ;再循环获取消息ExitLoop: MOV EAX,msg.wParam ;设置返回(退出)码 RETWinMain ENDP,返回,窗口消息处理程序,WndProc PROC hWn
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 七下创优数学试卷
- 青岛版六下数学试卷
- 去年襄阳中考题数学试卷
- 莆田中职学考数学试卷
- 二零二五年度储能电站设备升级与能源管理合同
- 二零二五年度金融领域个人劳务派遣管理合同
- 二零二五年度金融理财业务外包协议
- 宁波大学离散数学试卷
- 2025年度冷链物流运输预付款合同书
- 2025年度商业街区商铺翻新与特色文化主题设计服务合同
- 《建筑装饰设计收费》
- 新版外研版九年级英语上单词-默写纸-完整
- 设备预防性维修管理
- 经阴道后穹窿穿刺课件
- 去极端化自我剖析
- 船舶压载水取样与检测技术
- 人工流产后避孕服务规范
- 环境、社会与公司治理(ESG)
- 学校食堂食材配送服务方案(肉类、粮油米面、蔬菜水果类)(技术标)
- 物理学与人类文明(绪论)课件
- 《圆的周长》说课ppt
评论
0/150
提交评论