汇编语言程序设计及上机指导第7章高级汇编语言程序设计.ppt_第1页
汇编语言程序设计及上机指导第7章高级汇编语言程序设计.ppt_第2页
汇编语言程序设计及上机指导第7章高级汇编语言程序设计.ppt_第3页
汇编语言程序设计及上机指导第7章高级汇编语言程序设计.ppt_第4页
汇编语言程序设计及上机指导第7章高级汇编语言程序设计.ppt_第5页
已阅读5页,还剩23页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第7章 高级汇编语言程序设计,【本章提要】 本章叙述几种难道较大的程序设计技术,包括CPU工作模式的切换,以及32位和64位Windows汇编语言程序的设计,最后讲述汇编语言和高级语言的简单混合编程。 【学习目标】 掌握32位、64位Windows程序的汇编语言设计的基本方法 简单掌握MASM32以及FASM汇编工具的基本应用 简要掌握汇编语言和高级语言的混合编程及其汇编、编译和 链接过程,2019年4月28日星期日,7.1 保护模式编程介绍,7.1.1 保护模式的特征 实模式下的寄存器、寻址方式和指令等基本概念,除特别说明外在保护方式下仍然保持。尽管实方式下CPU的功能要大大超过其先前的处理器,但只有在保护方式下,才能发挥其更大的作用。 在保护方式下,全部32条地址线有效,可寻址高达4G字节的物理地址空间;扩充的存储器分段管理机制和可选的存储器分页管理机制,不仅为存储器共享和保护提供了硬件支持,而且为实现虚拟存储器提供了硬件支持;支持多任务,能够快速地进行任务切换和保护任务环境;4个特权级和完善的特权检查机制,既能实现资源共享又能保证代码和数据的安全和保密及任务的隔离;支持虚拟8086方式,便于在保护方式下同时又能执行8086程序。,2019年4月28日星期日,7.1.2 保护模式编程,保护模式编程的要点就是如何实现实模式和保护模式的相互切换。 一、从实模式切换到保护模式 从实模式切换到保护模式一般需要两个步骤: 作好切换到保护模式下的准备; 切换到保护模式。 主要准备工作就是建立全局描述符表,并使GDTR指向GDT,因为切换到保护模式下,至少要将代码段的选择子装入到CS中。,2019年4月28日星期日,1)定义好段描述符的结构: DESCRIPTOR STRUCT ;每个段描述符占8个字节 LIMIT DW 0 ;段界限 BASEL DW 0 ;段基址的低16位 BASEM DB 0 ;段基址的1623位 ATTRIBUTES DW 0 ;段属性 BASEH DB 0 ;段基址的高8位,2431 DESCRIPTOR ENDS 2)定义好伪描述符: PDESCRIPTOR STRUCT ;装入48位全局描述符表寄存器时要用到 LIMIT DW 0 ;段界限 BASE DD 0 ;段基址 PDESCRIPTOR ENDS 3)通常要定义一个段间跳转的宏,这样的话就可以保证在进入保护模式时将代码段的选择子装入到CS寄存器。 JUMPFAR MACRO selector,offsets DB 0EAH ;0EAH为JUMP指令的机器码 DW offsets ;段偏移 DW selector ;段选择子 ENDM,2019年4月28日星期日,4)打开A20地址线:保护模式下访问的地址空间超过1M,所以必须要用到A20地址线。 ENABLE_A20 MACRO ;通过92H号端口的输出,可以使地址线 ;A20打开,能够被访问 PUSH AX IN AL,92H OR AL,2 ;在92H号端口的d1位输出1,打开A20地址线 OUT 92H,AL POP AX ENDM 5)切换到保护模式下的最关键的动作为,将CR0寄存中的第0位置1。 TO_PROTECT MACRO MOV EAX,CR0 OR CR0,1 MOV CR0,EAX ENDM,2019年4月28日星期日,二、保护模式切换到实模式 显而易见,在保护模式返回到实模式时,只要做和上述的几个动作相反的动作就行了。主要要做好以下几个方面: 1)定义一个宏,回到实模式,将CR0寄存中的第0位清0。 TO_REAL MACRO mov eax,cr0 and eax,0fffffffeh mov cr0,eax ENDM 2)定义一个宏,关闭A20地址线。 DISABLE_A20 MACRO PUSH AX IN AL,92H AND AL,0FDH ;在92H号端口的d1位输出0,关闭A20地址线 OUT 92H,AL POP AX ENDM 3)恢复DS,使其内容为数据段基址,可用以下两条指令: mov ax,DATA mov ds,ax 4)用一个段间跳转的宏,清指令预取队列,使CS内容为代码段基址。,2019年4月28日星期日,三具体实现方法 下面的例子给出了如何从实模式转换到保护模式,并在保护模下访问680000H单元开始的内容(数据段基地址为680000H),最后又如何从保护模式返回到实模式的方法,程序结构片段如下: .386P ;定义使用386指令集 data segment use16 ;定义16位数据段 GDT LABEL BYTE ;定义全局描述符表 EMPTY DESCRIPTOR ;空描述符, CODESEG DESCRIPTOR0FFFFH,98H, ;代码段的描述符 CODE_SEL=CODESEG-GDT ;代码段描述符的选择子 DATASEG DESCRIPTOR0FFFFH,0H,68H,92H, ;数据段描述符,即680000H DATA_SEL=DATASEG-GDT ;数据段选择子 GDTLEN=$-GDT VGDTR PDESCRIPTOR GDTLEN-1, data ends,2019年4月28日星期日,code segment use16 assume cs:code,ds:data start: mov ax,data mov ds,ax mov bx,16 mul bx ;设置全局描述表GDT基址,因为现在还处在实模式下,所以段地址要左移4位 add ax,offset GDT adc dx,0 mov word ptr VGDTR.BASE,ax ;设置全局描述符表寄存器GDTR的内容 mov word ptr VGDTR.BASE+2,dx mov ax,cs ;以下为设置代码段描述符 mul bx mov CODE.BASEL,ax mov CODE.BASEM,dl mov CODE.BASEH,dh LGDT FWORD PTR VGDTR ;加载GDTR CLI ;关中断 ENABLE_A20 ;打开A20地址线 TO_PROTECT ;切换到保护模式 JUMPFAR Code_Sel, ;清指令预取队列, PROTECT: ;现在开始在保护方式下运行 mov ax,Data_Sel mov ds,ax ;加载数据段描述符 ;根据具体任务要求实现程序段 ;以下为回到实模式的步骤 JUMPFAR , ;清指令预取队列 REALMODE: TO_REAL ;回到实方式 DISABLE_A20 ;关闭A20地址线 mov ax,DATA mov ds,ax STI;开中断 ;根据具体任务要求实现程序段 code ends end start,2019年4月28日星期日,7.2 用汇编语言编写Windows应用程序,7.2.1 Windows与DOS区别 一、工作方式 16位DOS操作系统工作于实地址方式,是单任务操作系统,一个正在运行的程序独占了所有系统资源,只有一个特权级别,任何程序和操作系统都是同级的。 32位Windows操作系统运行于IA-32微处理器的保护地址模式,是多任务操作系统,系统资源由多个程序共享,系统存在两个特权级别,操作系统运行在最高级别0级,应用程序都运行于最低级别3级。 64位Windows操作系统运行于64位模式下,和32位Windows操作系统的特征基本类似,但只能工作在支持EM64T技术的IA-32或IA-64处理器环境中,目前主要有64位版的Windows XP和64位版的Windows Vista。,2019年4月28日星期日,二、内存空间 DOS平台下只能访问1MB物理存储空间,而且内存必须分成不大于64KB的逻辑段,由不同的段寄存器来寻址不同的段。 32位Windows平台下,直接使用32位地址来寻址一个不分段的、达4GB的主存空间,Windows应用程序只有代码段和数据段,无须和段寄存器打交道。只有一种内存管理模式FLAT。 64位Windows平台下,默认采用64位线性地址空间,支持40位物理地址空间,通常不采用分段方式,而是将CS,DS,ES和SS的段基址看成0,这样线性地址等于有效地址,也是只有一种FLAT存储管理模式。,2019年4月28日星期日,三、系统功能调用 DOS操作系统为程序员提供中断服务程序,以中断调用的方法进行系统功能调用,而且DOS中断调用采用寄存器传递参数; Windows32/64操作系统提供了动态链接库DDL,利用应用程序接口API(也曾被称为软件开发包SDK)调用动态链接库中的函数,应用程序利用堆栈传递参数。 四、输入输出方式 DOS平台下的程序以字符方式输出信息,程序需要用户输入数据时就停下来,一直等到用户输入了数据之后才继续执行; Windows32/64程序采用图形用户界面进行信息的输入输出,用户的每个操作都会形成消息(Message)传递给相应程序,各个同时运行的程序彼此之间相对独立。,2019年4月28日星期日,masm32子文件夹介绍,2019年4月28日星期日,MASM32QEDITOR.EXE集成开发工具,2019年4月28日星期日,在windows.inc文件中关于UType的定义: MB_ABORTRETRYIGNORE ;消息框有三个按钮:.终止.,.重试.和.忽略. MB_HELP ;消息框上显示一个.帮助.按钮,按下后发送WM_HELP消息 MB_OK ;消息框上显示一个.确定.按钮,这是默认值 MB_OKCANCEL ;消息框上显示两个按钮:.确定.和.取消. MB_RETRYCANCEL ;消息框上显示两个按钮:.重试.和.忽略. MB_YESNO ;消息框上显示两个按钮:.是.和.否. MB_YESNOCANCEL ;消息框上显示三个按钮:.是.、.否.和.取消. 要在消息框中显示图标,用下面的某一个标志: MB_ICONWARNING ;显示惊叹号图标 MB_ICONINFORMATION ;显示消息图标 MB_ICONASTERISK ;显示危险图标 MB_ICONQUESTION ;显示问号图标 MB_ICONSTOP ;显示停止图标,2019年4月28日星期日,简单Win64程序设计,format PE64 GUI ;定义64位程序 entry start ;指定程序入口为start标号 section .codecode readable executable ;定义代码段 start: ;程序入口标号 sub rsp,8*4 ;为API调用预留堆栈空间并使rsp指针64位对齐 mov r9d,1 ;r9d寄存器用于传送MessageBoxA函数的按钮参数 lea r8,caption ;r8寄存器用于传送MessageBoxA函数的标题参数 lea rdx,message ;rdx寄存器用于传送MessageBoxA函数的文本参数 mov rcx,0 ;rcx寄存器用于传送消息框的类型参数 call MessageBoxA ;调用MessageBoxA函数,显示消息框 mov ecx,eax ;把eax中消息框的返回值保存到ecx call ExitProcess ;调用ExitProcess 函数,结束程序并返回到OS section .datadata readable writeable ;定义数据段 caption db Windows64位应用程序,0 ;定义消息框要显示的标题 message db 好好学习,天天向上!,0 ;定义消息框要显示的文本,用汇编语言开发64位Windows应用程序,首先要有64位的处理器和操作系统软硬件支持,另外还要选择合适的64位汇编工具。,2019年4月28日星期日,;以下是为程序的链接和执行所进行的辅助定义 section .idata import data readable writeable ;定义入口数据段 dd 0,0,0,RVA kernel_name,RVA kernel_table ;对程序装入时的预定义,以及对 ;所调用函数和API动态链接库的 dd 0,0,0,RVA user_name,RVA user_table ;声明等 dd 0,0,0,0,0 kernel_table: ExitProcess dq RVA _ExitProcess dq 0 user_table: MessageBoxA dq RVA _MessageBoxA dq 0 kernel_name db KERNEL32.DLL,0 user_name db USER32.DLL,0 _ExitProcess dw 0 db ExitProcess,0 _MessageBoxA dw 0 db MessageBoxA,0,2019年4月28日星期日,7.3.1 汇编指令的嵌入式编程,汇编指令的嵌入式编程就是在高级语言程序中,嵌入汇编语言指令。 一、嵌入方法 在Turbo C语言程序中,嵌入汇编语言指令是在汇编语句前加一个asm关键字。 语法如下: ASM 其中,操作码是处理器指令或若干伪指令;操作数是操作码可接受的数据,它可以是指令允许的立即数、寄存器名,还可以是C语言程序中的常量、变量和标号。内嵌的汇编语句可以用分号“;”结束,也可以用换行符结束;一行中可以有多个汇编语句,相互间用分号分隔,但不能跨行书写。嵌入汇编语句的分号不是注释的开始;要对语句注释,应使用C语言的注释,如*。例如: ASM MOV AX,BX; /* AXBX */ ASM POP AX;ASM POP BX ;ASM RET; /* 3条语句可以写在一行 */ ASM ADD AX, BX /* ASM语句在C程序中可以不用分号结尾*/,2019年4月28日星期日,在Turbo C 2.0中,具体说明如下: 1)持8086指令集,包括传送、运算、串操作、转移等全部指令。当内嵌80286指令时,必须使用TCC命令行选择项-L进行编译,以便使汇编程序能够识别这些指令。 2)仅支持若干汇编语言伪指令,它们是变量定义伪指令dbdwdd和外部数据说明伪指令extern。 3)Turbo C语言中可以直接使用通用寄存器和段寄存器,只要在寄存器名字前加一个下划线即可,但寄存器名字要大写。 4)嵌入式汇编语言中,可以使用无条件、条件转移指令和循环指令,但它们只能在一个函数内部转移。ASM语句也不能定义标号,转移指令的目标必须是C语言程序的标号。 5)若要嵌入一组汇编语句,则需要用括号和把它们括起来。例如: ASM MOV AX, DATA1 /*实现整型变量DATA1和DATA2之值的交换*/ XCHG AX, DATA2 MOV DATA1, AX ,2019年4月28日星期日,【例】在C语言源程序中嵌入汇编语言语句实现3个整数求和。 int sum3(int var1,int var2,int var3) ASM PUSH AX ASM MOV AX, VAR1 ASM ADD AX, VAR2 ASM ADD AX, VAR3 ASM MOV VAR1 , AX ASM POP AX return(var1) main() /*C语言主程序*/ printf(“%dn”,sum3(10,20,30); ,2019年4月28日星期日,二、嵌入汇编的编译过程,C语言程序中含有嵌入式汇编语言语句时,C编译器要完成以下三个步骤: 代码转换:将.C扩展名源程序的代码转换成.ASM扩展名的汇编语言代码源文件; 编译:用默认的汇编程序TASM.EXE把产生的.ASM汇编语言源文件编译成.OBJ目标文件,TASM与MASM基本相同,也可以在编译的命令行中加上-EMASM选项用MASM.EXE来编译。注意Tuorbo C 2.O是早期开发的软件,只考虑了与早期MASM版本的兼容,而不能与MASM 6.x很好的配合使用; 用TLINK将目标文件链接成.exe可执行文件。 Turbo C 2.0在编译含内嵌汇编语句的程序时,只能采用命令行方式,通过执行TCC.EXE来完成。同时要使用-B命令行选项编译连接,也可以在C源程序中使用了#pragma inline预处理语句,这时就可以不用命令行选项-B了。,2019年4月28日星期日,【例】将字符串中的大写字母转变为小写字母并显示出来 #include “stdio.h” void lower(char *dvar,char *svar) ASM MOV SI,SVAR * DVAR和SVAR是地址指针* ASM MOV DI,DVAR ASM CLD again:ASM LODSB *C语言定义的标号* ASM CMP A1,A ASM JB COPY *转移到C的标号* ASM CMP A1,Z ASM JA COPY *不是A到Z之间的字符原样复制* ASM ADD A1,20H *是小写字母转换成大写字母* copy:ASM STOSB * C语言定义的标号* ASM CMP AL,0 * C语言中字符串用0结尾 * ASM JNZ AGAIN; main() *主程序* char oldstr”IAM a good STUDENT!”; char newstr100; lower(newstr,oldstr); printf(“OLD STRING IS %sn”,oldstr); printf(“NEW STRING IS %sn”,newstr); ,2019年4月28日星期日,编辑完成后,假定该文件名为,在命令行输人如下编译命令(选项-I和-L分别指定头文件和库函数的所在目录): TCC B Iinclude Llib example.c 生成可执行文件example.exe,程序运行后输出的结果将是: OLD STRING IS IAM a good STUDENT! NEW STRING IS iam a good student! 由上例可以看出,嵌入汇编方式把插入的汇编语言语句作为C语言的组成部分,不使用完全独立的汇编模块,所以比调用汇编子程序更方便、快捷,并且在大存储模式、小存储模式下都能正常编译通过。,2019年4月28日星期日,7.3.2 多模块混合编程,各种语言的程序分别编写,利用各自的开发环境编译形成.obj目标模块文件,然后将它们连接在一起,最终生成可执行文件。 一、混合编程的规则 1命名规则 C语言编译系统在编译C语言源程序时,要将其中的变量名、过程名、函数名等标识符前面加下划线“_”;但是,如果汇编语言程序设置采用C语言类型,则不必在标识符前加下划线。而且对标识符的要求是取前8个字符有效还注意区别字母的大小写。 2声明规则 在C语言程序中,对所要调用的外部过程、函数、变量都要用EXTERN来说明,并且要求放在主调用程序之前,一般放在各函数体外部,说明形式如下: EXTERN 返回值类型 函数名称(参数类型表); EXTERN 变量类型 变量名; 其中,返回值类型和变量类型是C语言中函数、变量中所允许的任意类型,当返回值类型空缺时,默认为int型。例如: EXTERN long some(int,int); /*SOME函数返回值为LONG型*/ EXTERN good(int,int); /*GOOD函数返回值缺省为INT型*/ EXTERN char tempvar /*TEMPVAR变量为CHAR型*/ 经说明后,这些外部变量、过程、函数可在C程序中直接使用,函数的参数在传递过程中要求参数个数、类型、顺序要一一对应。 和纯汇编语言多模块编程要求一样,汇编语言程序的标识符(子程序名和变量名)为了让C语言程序能够调用它,必须用public语句定义它们。,2019年4月28日星期日,3寄存器使用规则 1)通用寄存器AX、BX、CX、DX和ES,在汇编语言子程序中通常是可以任意使用的。一般传递返回值的任务由AX和DX寄存器承担。标志寄存器也可以任意改变; 2)段寄存器DS、CS和SS 及BP、SP,如果汇编语言子程序要使用它们,必须先进行保护(入栈),退出前再加以恢复(出栈); 3)变址寄存器SI和DI一般被作为Turbo C寄存器变量,所以汇编语言子程序使用SI和DI时也要进行保护和恢复。但如果C程序没有用到寄存器变量,则汇编语言子程序不必多此一举。 4存储模式规则 Turbo C提供了6种存储模式,分别对应了汇编程序的前6种相应存储模式。为了使汇编语言程序与Turbo C语言程序连接到一起,两者必须具有相同的存储模式。汇编语言程序采用.model伪指令,Turbo C利用TCC命令行的选项-m指定各自的存储模式。相同的存储模式将自动产生相互兼容的调用和返回类型;另外,汇编程序的段定义伪指令.Code、.data等也会产生与Turbo C相兼容的段名和属性,2019年4月28日星期日,模块的编译和连接,采用AX寄存器传递返回,通过堆栈传递参数。 【例】C语言程序调用汇编语言子程序,计算周工资并显示总和。假定C语言主程序保存 在文件c_main.c中,内容如下: /*WEEKPAY是外部函数*/ extern unsigned short weekpay(int,wages) int wages5=100,200,120,280,150 main() printf(“WEEKLY PAY=%u”,weekpay(wages); /*调用WEEKPAY函数*/,2019年4月28日星期日,假定汇编语言子程序保存在文件masm_sub.asm中, 内容如下: .MODEL MEDIUM,C ;采用中型存储模式和C语言类型 .CODE PUBLIC WEEKPAY ;指明该过程可供外部模块使用 WEEKPAY PROC FAR ;采用了一致的命名约定,共用标识符不必加下划线 PUSH BP ;保护寄存器BP,子程序第一条语句必须是它 MOV BP,SP ;取当前栈顶SP地址 PUSH SI ;保护寄存器SI SUB AX,AX ;AX清零 MOV CX,5 MOV SI,BP+6 ;SI为C主程序调用时第一个实参在堆栈中的地址 GOON:ADD AL,SI ;把SI所指向的参数累加到AL中 ADC AH,0 ;考虑进位 INC SI INC SI LOOP GOON POP SI ;恢复寄存器 POP BP RET ;返回,子程序最后一条语句必须是它 WEEKPAY ENDP END,2019年4月28日星期日,关于被调用函数的返回值,一般按照下列规则传递给调用者: 若返回值不超过16位,则由AX寄存器来传递,上例就是用这种方法实现的; 若返回

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论