第4章----汇编与C混合程序设计_第1页
第4章----汇编与C混合程序设计_第2页
第4章----汇编与C混合程序设计_第3页
第4章----汇编与C混合程序设计_第4页
第4章----汇编与C混合程序设计_第5页
已阅读5页,还剩34页未读 继续免费阅读

下载本文档

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

文档简介

第4章汇编语言程序设计汇编语言是以处理机指令系统为基础面向机器的语言。用汇编语言编写程序的主要优点是程序设计人员可以直接对存储器、CPU内部寄存器和输入/输出端口编程,程序效率高,执行速度快;汇编语言源程序比高级语言源程序生成的目标代码短,占用存储空间少,因而在对于程序空间和时间要求很高的场合,如系统软件设计、实时控制系统和I/O接口驱动程序的设计中,汇编语言的作用是不可代替的,至于对很多需要直接控制硬件的场合,汇编语言的作用更是必不可少的。但是汇编语言要求程序员了解计算机的硬件,并对计算机的指令系统比较熟悉;另外不同的处理器有不同指令系统,故不同机器之间汇编语言程序难以移植,这些也限制了汇编语言的应用范围。汇编语言的源程序是不能直接运行的,要用汇编程序对源程序进行汇编,翻译成机器语言目标程序,再连接形成可执行的程序,才能交付计算机执行。汇编程序是实现把汇编语言源程序翻译成目标程序的一种系统软件。汇编语言源程序是由汇编指令、汇编伪指令等按照规定的语法规则编写的。本章介绍了汇编语言程序的编程格式、基本的汇编语言伪指令,并以分支程序、循环程序、子程序和DOS系统功能调用为例,论述汇编语言的基本程序设计方法,还介绍了汇编语言与C语言的混合编程方法,最后给出了汇编语言程序上机过程。本章的重点是掌握汇编语言程序的基本设计方法,正确使用程序结构及常用伪指令,掌握分支、循环、子程序的设计方法和DOS功能调用。本章的难点是正确理解和掌握伪指令的应用以及子程序的设计。41汇编语言源程序的语句类型80X86宏汇编语言有两种基本语句:指令语句和指示语句(伪指令语句)。指令语句是可执行语句,它要求CPU执行某种操作。在汇编时产生一一对应的机器目标代码。指令语句的格式为:标号: 指令助记符操作数;注释一条指令可以由4个字段组成,其中,方括号内的字段为可选项。指令语句的详细说明见3.1节。指示语句又称伪指令或伪操作。伪指令是不可执行语句,它只是在源程序汇编期间给汇编程序提供汇编信息,如指示汇编程序为数据分配内存空间、或者提供段定义的信息等,不产生任何机器代码,伪指令与机器指令无关。伪指令的格式为:符号名 伪指令定义符参数表;注释本章的4.2节将介绍80X86的常用伪指令。42 80X86汇编语言的数据和表达式汇编语言程序的语句,是按照汇编语言的基本语法书写的,汇编语言语句中的数据、表达式和运算符也是指令的一个重要组成部分,数据、表达式和运算符的格式对指令有很大的影响。下面对此加以讨论。421常量1.常量的类型常量是汇编时已确定的值,在程序运行中,常量的值不会改变。例如,立即寻址时所用的立即数,直接寻址时所用的地址等都是常量。常量有两种类型:数值型常量和字符串型常量。(1) 数值型常量二进制数:以字母B结尾,例如:B。十进制数:以字母D结尾(或省略),例如:3876,3421D。八进制数:以字母Q或O结尾,例如:765Q、321O。十六进制数:以字母H结尾,由09,AF所组成,为了避免与字母开头的标识符相混淆,汇编语言规定,凡是以字母AF开头的十六进制数,必须在字母前加上数字0。例如:89ABH、0FFB0H等。(2) 字符串常量字符串常量是用单引号或双引号括起来的一个或多个字符串,如ABC或“ABC”等,字符在机器内是以ASCII码存放,例如,B在内存中为42H。常量可以用数值形式直接写在汇编语言语句中,也可以预先为它定义一个名字,供程序员编程时直接引用。2.常量或表达式赋值伪指令对于程序中多次出现的同一个常量或表达式可以用表达式赋值伪指令给表达式赋予一个新的符号,此后,程序中凡是需要用到该表达式之处就可以用这个符号名来代替了,从而给程序设计带来很大的方便和灵活性。(1) 等值伪指令(EQU)格式:符号名 EQU 表达式功能:将表达式的值赋给符号名。例41CONT EQU 128;定义常数CONT=128 NUM EQUALPH+8 ;定义表达式NUM等于表达式的值 ADDR EQUDS:EBP+4;加段前缀的变址寻址赋以符号名ADDR 等值伪指令在汇编时不产生任何目标代码,也不占用存储单元。但在同一个程序中,不能对已定义的符号重新定义。 (2)等号伪指令格式:符号名= 表达式功能:将表达式的值赋给符号名。例42COUNT=20HABC=3.ABC=ABC+6COUNT=COUNT+10H等号语句与EQU语句有同样的功能,区别在于在同一源程序中,EQU语句不允许对符号重新定义,而等号语句允许对符号多次定义。422 变量变量用来定义存放在存储单元中的数据,变量名是存放数据的存储单元的地址,变量的值为对应存储单元的内容。与常量不同的是变量的值可以在程序的运行过程中随时修改。1变量的属性变量有三种属性:(1)段属性(SEG)段属性是指所在段的段基址,它通常放在DS、ES、SS段寄存器中。 (2)偏移属性(OFFSET),指变量所在段中的偏移地址,即变量所在的地址与段基址之间的字节数。 (3)类型属性(TYPE),指变量占用存储单元的字节数。若占用一个字节,称为字节变量,其类型为BYTE;若占用两个字节,称为字变量,其类型为WORD;若占用四个字节,称为双字变量,其类型为DWORD;此外还有六字节、八字节和十字节变量,它们分别占用3个字存储单元、4个字存储单元和5个字存储单元,其类型为FWORD、QWORD和TBYTE。2变量定义伪指令变量定义伪指令是为数据分配存储单元,并给这个存储单元取一个名字,即变量名。格式:变量名DB/DW/DD/DF/DQ/DT表达式1,表达式2,功能:为变量分配1个字节/字/双字/长字/4字/10字节存储单元,表达式可以是数值表达式、地址表达式、字符串、?、用逗号隔开的上述各项或n DUP(表达式)。(1) 数值变量定义语句例4.3 NUMDB100,45H;将64H,45H赋给字节变量NUMSUMDW3456H;将3456H赋给字变量SUMTOTALDDH;将赋给双字变量TOTAL变量NUM、SUM和TOTAL在存储单元中的存放格式如图4.1所示。数据存放时低字节存放在低地址,高字节存放在高地址。(2) 字符串变量定义语句定义字符串变量可以用DB伪指令,它为字符串中每个字符分配一个字节存储单 元,在存储单元中存放的是字符的ASCII码。DW伪指令也可以定义字符串变量,即给两个字符组成的字符串分配两个字节存储单元。例4.4ABCDBABCDEF ;将字符串赋给变量ABCDATEDWAB,CD ;给AB,CD字符串各分配两个节存储单元。变量ABC、DATE在存储单元中的存放格式如图4.2所示。低地址低地址NUM 64 ABCA 45 BSUM 56 C 34 DTOTAL 55E 44F 33DATE B 22A高地址DC高地址图4.1 数值变量存储格式图4.2 字符串变量存储格式(3)?伪指令 ?语句也是为数据项分配存储单元,但是存储单元中不预置确定的值,常用来预留存储单元。例4.5FIRSTDB?;分配一个字节单元SECONDDW?,?,?;分配三个字单元(4)重复数据定义伪指令(DUP) DUP(Duplication)是重复数据定义操作,用带DUP的表达式可以为若干重复数据分配存储单元,DUP表达式也可以嵌套。例4.6D1DB5 DUP(0);定义D1为5个全为0的字节单元 D2DW10 DUP(22AAH);定义D2为10个全为22AAH的字单元 D3DD20DUP(?);定义D3为20个预留的双字单元 D4DB3 DUP(10H,2DUP(80H);定义D4为(10H,80H,80H)重复3次共9个字节。423标号标号是可执行语句的符号地址。用来表示指令在存储器中的位置,标号可作为转移指令的目标操作数,以决定转移指令的目标地址。标号之后必需有一个冒号(:),标号也可以单独占一行。1标号的属性:(1)段属性(SEG),段属性是指标号所在段的段基址,它通常放在DS、ES、SS段寄存器中。 (2)偏移属性(OFFSET)。指标号所在段中的偏移地址,即标号所在的地址与段基址之间的字节数。 (3)类型属性或距离属性(TYPE),用来说明该标号是段内引用还是段间引用。段内引用时为NEAR属性,指针占2个字节;段间引用时为FAR属性,指针占4个字节。 标号的距离属性可以用LABEL伪指令加以改变。2用LABEL伪指令定义标号的类型属性LABEL伪指令为当前存储单元定义一个指定类型的变量或标号。如果LABEL定义的是变量,其类型可以是BYTE、WORD或DWORD;如果定义的是标号,其类型可以是NEAR或FAR,隐含的类型为NEAR。语句格式如下:变量名或标号 LABEL类型(1) 与变量连用LABEL与变量连用,用来给下一条语句中的变量取一个新的名字,并可重新定义它的类型。例4.7 B-ARRAYLABELBYTEW-ARRAYDW50DUP(?) 这两条语句给100个字节的数组定义了两个不同类型的变量名:字节类型变量B-ARRAY和字类型变量W-ARRAY。这样在后续的语句中,如果以字类型访问该变量,应使用字变量名,即W-ARRAY;若以字节类型访问该变量,应使用字节变量名,即B-ARRAY。例如: MOVW-ARRAY+2,0;把该数组的第3、第4个字节置0MOVB-ARRAY+2,0;把该数组的第3个字节置0定义堆栈时,LABEL语句也经常用到。例4.8STACKSEGMENTDW30 DUP(?)TOP LABELWORDSTACKENDS这里定义了一个由30个字组成的堆栈,栈底取名为TOP,其类型定义为字。(2) 与标号连用LABEL与标号连用时用来给指令地址定义一个新的标号,并可改变其类型属性。例4.9DISTFARLABELFARDISTNEAR:MOVAX,BX+SI 这里第二条语句用冒号隐含定义了DISTNEAR为NEAR属性,第一条LABEL语句给第二条语句的标号取一个新的标号名DISTFAR,并将属性改为FAR。DISTFAR和DISTNEAR有相同的逻辑地址,但它们的类型属性不同,可作为程序转移或调用时不同情况下的入口。当在段内转移时用,可使用标号名DISTNEAR,在段间转移时用,可使用标号名DISTFAR,但实际上是指向同一条指令。424表达式表达式是由常量、变量、寄存器、标号以及连接它们的运算符组成。表达式的运算是在汇编时由汇编程序完成的,表达式的运算的结果作为操作数参加指令规定的操作。MASM宏汇编允许使用的表达式有两种类型:数值型表达式和地址表达式。1.数值表达式 数值表达式的结果是数值。例如:MOVAX,(NUM*6+10H)/5指令中源操作数是一个表达式,其运算结果是一个数值,指令执行后AX中是该表达式的值。2.地址表达式 地址表达式的结果是一个存储单元的地址。当这个地址中存放的是数据时,称为变量;当这个地址中存放的是指令时,则称为标号。例如:MOVAX,ES:BX+SI+100H。指令中源操作数是地址表达式,其结果是一个存储单元的地址。425运算符运算符分为算术运算符、逻辑运算符、关系运算符、属性运算符、数值返回运算符和其它运算符等。1 算术运算符 算术运算符包括:+(加)、(减)、*(乘)、/(除)和MOD(模除)、SHL(左移)和SHR(右移)。+、*、/是常用的运算符,参加运算的数和运算的结果均为整数,除法运算的结果取商的整数部分,MOD模除运算只取其余数。SHL左移和SHR右移运算,相当于二进制乘法和除法运算。 2逻辑运算符 逻辑运算符包括AND(与)、OR(或)、异或(XOR)、NOT(非)四种。用于对常量进行按位操作。注意,这四种运算符与逻辑指令的助记符是一样的,但它们在语句中的为置是不同的。表达式中的逻辑运算符是只出现在指令的操作数部分,是由汇编程序汇编时完成运算;而逻辑指令是中的助记符是出现在指令的操作码部分,其运算是在指令执行时进行的。 例4.10ORAL,BH OR 80HMOVAL,CL AND B3.关系运算符关系运算符包括GT(大于)、GE(大于等于)、LT(小于)、LE(小于等于)、EQ(等于)、NE(不等于)共六种。关系运算符用于对两个操作数进行比较运算,结果为逻辑值。若关系成立结果为真,用全“1”表示;结果为假,用全“0”表示。例4.11MOVAX,10EQ1010B;10=1010B为真,(AX)=0FFFFHMOVBX,20H GT32;20H大于32为假,(BX)=04属性运算符属性运算符有PTR和THIS两种。它们可以临时改变原操作数的类型属性,一般对存储器操作数使用。例4.12DATA1DB10,11,12,13,14,15,16 ADDWORDPTRDI,100;指明目标操作数是字类型JMPDWORD PTRBX;指明为段间转移MOVEAX,DWORD PTR DATA1;修改DATA1为双字型变量ALPHA EQU THIS BYTE;将变量ALPHA的类型定义为字节POINT EQU THIS FAR;将标号POINT定义为FAR5数值返回运算符数值返回运算符包括SEG(返回段地址)、OFFSET(返回偏移地址)、TYPE(返回类型字节数)、LENGTH(返回变量单元数)和SIZE(返回变量总字节数)。它们不改变原操作数的属性,只是取操作数的某一属性,返回的结果是一个数值。(1) SEG运算符SEG运算符加在变量名或标号之前,返回的数值是该变量或标号所在段的段基址。例如:MOVAX,SEG VAR1如果变量VAR1所在段的段基址为2000H,则该指令执行后AX的内容为2000H。(2) OFFSET运算符OFFSET运算符加在变量名或标号之前,返回的数值是该变量或标号所在段的偏移地址。例如:MOVBX,OFFSET NEXT如果变量NEXT在段内的偏移地址为100H,则该指令执行后BX的内容为100H。(3)TYPE运算符 TYPE运算符加在变量名之前,返回的数值是该变量的类型字节数,如:DB为1,DW为2,DD为4,DQ为8,DT为10;当TYPE加在标号之前,返回的数值是这个标号的类型属性值,如:NEAR为1,FAR为2。 例4.13A1DB5,6,7,A2DW1234H,3456HA3DDHSFLABEL FARSN:MOVBL,TYPEA1;等效于MOVBL,1MOVBH,TYPEA2;等效于MOVBH,2MOVDLTYPEA3;等效于MOVDL,4MOVDH,TYPESF;等效于MOVDH,2(4)LENGTH运算符该运算符加在变量名之前,返回的数值是该变量中所定义的元素个数。如果变量是用重复数据操作符DUP说明的,则返回DUP前面的数值,如果没有DUP说明,则返回的值总是1。例4.14B1DB100H DUP(0)B2DW20H DUP(0)B3DW4321H,3859HB4DBABCDEFMOVBX,LENGTH B1;等效于MOV BX,100HMOVCX,LENGTH B2;等效于MOV CX,20HMOVDX,LENGTH B3;等效于MOV DX,1MOVAX,LENGTH B4;等效于MOV AX,1(5)SIZE运算符该运算符加在变量名之前,返回的数值是该变量所杂烩的字节总数。它等于LENGTH和TYPE两个运算符返回的乘积。例如,对于上例中所定义的变量B1、B2、B3、B4,SIZE的返回值如下所示:例4.15MOVBX,SIZE B1;(BX)=100HMOVCX,SIZE B2;(CX)=40HMOVDX,SIZE B3;(DX)=2MOVAX,SIZE B4;(AX)=16其它运算符(1)字节高低分离运算符HIGH和LOW运算符分别用于从16位运算对象中分离出高字节和低字节。MASM6.0 用HIGHWORD和LOWWORD运算符,从32位符号常量中分离出高字和低字。例4.16MOVAL,LOW1234H;(AL)=34HMOVAH,HIGH1234H;(AH)=12HVAREQU1234ABCDHMOVAX,HIGHWORD VAR;(AX)=1234H(2)运算符的优先级顺序上述运算符可以同时出现在表达式中,其优先级顺序由高到低如下所示:( ), , ,LENGTH,WIDTH,SIZE,MARKPTR,OFFSET,SEG,TYPE,THIS,CS:,DS:,SS:,ES:HIGH,LOW+,*,/,MOD,SHL,SHREQ,NE,LT,LE,GT,GENOTANDOR,XORSHORT43 80X86宏汇编语言的伪指令80X86宏汇编语言(MASM)提供了多种伪指令,主要有变量定义、符号定义、段定义、段分配、过程定义、模块定义、结构定义、宏定义等。上一节已经介绍了部分伪指令,在这一节里,我们介绍其它常用的伪指令,还有另外一些,需要时读者可查阅有关资料。431简化的段定义和完整的段定义在汇编语言程序设计中,存储器的物理地址是由段地址和偏移地址组合而成的,汇编程序在把源程序转换为目标程序时,必须确定标号和变量的偏移地址,并且需要把有关信息通过目标模块传送给连接程序,以便连接程序把不同的段和模块连接在一起形成一个可执行程序。为此需要用段定义伪操作。 在MASM5.0以上的汇编语言的版本中,段的定义有简化的段定义和完整的段定义两种伪指令。简化的段定义使用指定的存储模式编程,给程序设计带来极大的方便。简化的段定义常用伪指令如下:1MODEL伪指令格式如下:.MODEL存储模式,语言类型,操作系统类型,堆栈类型方括号内为可选项。.MODEL伪指令确定了程序的存储模式。当使用简化段定义的源程序格式时,必须有该语句,且位于所有简化段定义语句之前。(1)存储模式存储模式是指用户程序的数据和代码的存放格式,以及它们占用内存的大小。常用的存储模式有以下7种:TINY微型模式。程序中的数据和代码放在同一个64KB段内,其数据和代码都是近访问。这也就是.COM文件的格式,COM程序必须从0100H存储单元开始。这种模式一般用于小程序。SMALL小型模式。独立的代码段(64KB字节内)和独立的程序段(64KB字节内)。数据和代码都是近访问,一般程序默认的都是该模式。MEDIUM中型模式。一个数据段(64KB字节内),多个代码段。这样,数据是近访问,代码可以是远访问。COMPACT压缩模式。一个代码段(64KB字节内),多个数据段。这样,对于代码的访问是近程的,而数据是远程的。LARGE大型模式。多个代码段,多个数据段。对于代码和数据的访问都是远程的。HUGE与LARGE模式相同,其差别是允许数据段的大小超过64KB。FLAT平展模式。用于创建一个32位的程序,它只能运行在32位80X86CPU上。DOS下不能使用FLAT模式。MASM6.0支持该模式。(2)语言类型语言类型是高级语言接口选项,是指该汇编语言程序作为某种高级语言程序的过程而为该高级语言程序所调用时,应该用如C、BASIC、FORTRAN、PASCAL等加以说明。(3)操作系统类型 操作系统类型选项是说明运行于那个操作系统之下,OSDOS是当前唯一支持的选项,默认是OSDOS。 (4)堆栈类型 该选项可用NEARSTACK或FARSTACK来说明。其中,NEARSTACK是该选项的默认堆栈类型。NEARSTACK是堆栈段和数据段是同一个段。 FARSTACK堆栈段和数据段是不同的段。当存储模式为TINY、SMALL、MEDIUM和FLAT时,默认项是NEARSTACK;当存储模式为COMPACT、LARGE和HUGE时默认项是FARSTACK。例如:.MODELSMALL,C.MODELLARGE,PASCAL,OSDOS,FARSTACK2段定义伪指令简化的段定义伪指令都可以用来表示一个段的开始,同时也说明前一个段的结束。.CODE定义代码段.DATA定义数据段.DATA?.STACK长度定义堆栈段,长度缺省为1KB.STARTUP指示程序开始.CONST定义常数段.X86选择80X86的指令系统.EXIT0程序结束,返回操作系统当使用简化段伪指令时,必须在简化段伪指令之前先使用.MODEL伪指令定义存储模式,然后再用简化的段定义伪指令。3处理器选择伪指令MASM宏汇编在能够汇编指定处理器的指令,可采用下述伪指令:.8086可用来汇编8086/8088处理器的指令,这是缺省模式。.286、.286C、.286P可用来汇编286系列处理器的指令。其中.286、.286C可用于汇编非特权(实地址方式)80286处理器指令;.286P可用来汇编80286处理器的所有指令(包括保护方式)。.386、386C、.386P可用来汇编386系列处理器的指令。其中.386、.386C可用于汇编非特权(实地址方式)80386处理器指令;.386P可用来汇编80386处理器的所有指令(包括保护方式)。.486.、486C、486P可用来汇编486系列处理器的指令。其中.486、.486C可用于汇编非特权(实地址方式)80486处理器指令;.486P可用来汇编80486处理器的所有指令(包括保护方式)。.586.、586C、586P可用来汇编Pentium系列处理器的指令。其中,.586、.586C可用于汇编非特权(实地址方式)Pentium处理器指令;.586P可用来汇编Pentium处理器的所有指令。.686.、.686P可用来汇编Pentium Pro到Pentium 4处理器的指令。其中,.686可用于汇编实地址方式Pentium Pro到Pentium 4处理器指令;.686P可用来汇编Pentium Pro到Pentium 4处理器的所有指令。.MMX可用来汇编MMX指令。.MMX、.686和.686P是MASM6.12引入的。.K3D可用来汇编AMD处理器的3D指令,是MASM6.13引入的。.XMM可用来汇编SSE指令和SSE2指令,是MASM6.15引入的。需要说明的是,80386以上处理器选择伪指令在源程序中的位置不一样可有不同的含义。如果处理器选择伪指令放在.MODEL伪指令前面,段就定义成32位。如果希望处理器使用16位的段,则应在.MODEL伪指令的后面使用处理器选择伪指令。4等价名的使用MASM5.0宏汇编语言中,规定了几个等价名代替真实名。例如,段等价名可以用代替简化段定义伪指令前面的小数点。这样,CODE就代表.CODE定义的段名;DATA就代表.DATA、.DATA?、.CONST和.STACK.可共享的段组名。5段序定义伪指令MASM宏汇编可以按照源程序中各个段出现的次序来排列目标文件中各段的先后次序,也可以按照段名的字母顺序来排列次序。缺省是按照段出现的次序来排列,程序员可以用伪指令来定义段序,这些伪指令是:.ALPHA按照字母顺序对段进行排序。.SEG 按照段出现的顺序对段进行排序。完整段定义语句中,默认按此顺序。.DOSSEG按照DOS定义的标准段序对段排序,顺序为:代码段、数据段、堆栈段。采用.MODEL伪指令的简化段定义格式默认按此顺序。 6简化段定义结构举例例4.17.MODELSMALL ;定义小型内存模式.486 ;可以汇编486指令.STACK200 ;定义堆栈段,长度为200个字节.DATA ;定义数据段开始XXDW6789H,4321HYYDW0AB00H,00FFHZZDD?,?.CODE ;代码段开始.STARTUP ;程序开始MOVEAX,XXMULYYMOVZZAXMOVZZ+4,EDX.EXIT0;程序结束,返回DOS。相当于MOV AX,4C00H和INT 21H两条END ;汇编结束例4.18将数据区的信息显示在屏幕上。.MODELSMALL.586.STACK20H.DATAMSGDBTHIS IS A DISPLAY BUFFER$;显示的信息.CODE.STARTUPMOVDX,OFFSET MSG ;信息缓冲区首地址送DXMOVAH,9 ;将数据区的信息显示在屏幕上INT21H ;DOS显示功能调用.EXIT0 ;返回END ;汇编结束432完整的段定义伪指令完整的段定义伪指令适用于MASM和TASM。1完整的段定义结构举例例419DATASEGSEGMENT;数据段定义 BLOCKDB1000DUP(?)DATASEGENDS;数据段结束STACKSEGSEGMENT;堆栈段定义 DW100DUP(?)STACKSEGENDS;堆栈段结束EXTRASEGSEGMENT;附加段定义 DB 100DUP(?)EXTRASEGENDS;附加段结束CODESEGSEGMENT;代码段定义 ASSUMECS:CODESEG,DS:DATASEG,ES:EXTRASEG ASSUMESS:STACKSEG;分配段地址寄存器START:MOVAX,DATASEG MOVDS,AX MOVAX,EXTRASEG MOVES,AX MOVAX,STACKSEG MOVSS,AX : : MOVAH,4CH INT21HCODESEGENDS;代码段结束 ENDSTART2段定义伪指令格式:段名SEGMENT 定位类型,组合类型,字长选择,类别名:段名ENDS 任何逻辑段总是从SEGMENT语句开始,以ENDS语句结束。伪指令SEGMENT和ENDS不可以缺省,而且总是成对出现。段名是必选项,同一个段的开始和结束的段名应是相同的。方括号中的项是可选项。(1)定位类型(ALIGN TYPE)定位类型表示对段的起始边界的要求。有以下几种选择:PAGE(页):表示段从页的边界开始。256个字节为一页。PARA(节):表示段从节的边界开始。一节为16个字节,PARA通常为隐含。DWORD(双字):表示段从4的倍数地址开始。WORD(字):表示段从偶数地址开始。BYTE(字):表示段可以从任何地址开始。(2)组合类型(COMBINE TYPE)组合类型表示多个程序模块连接时,本模块与其它模块的同名段如何组合,可以有如下几种选择:PRIVATE:这是隐含选择,表示该段与其它段无组合关系,每段都有自己的段基址。PUBLIC:该段可与其它模块中的同名段在满足定位类型的前提下,从低地址到高地址连接起来,组合成一个较大的逻辑段。COMMON:表示产生一个覆盖段。即当两个段连接时,把本段与其它段也用COMMON说明的同名段置成相同的起始地址,共享相同的存储区,共享存储区的长度由其中最大的段确定。STACK:表示该段为堆栈段。连接程序将把不同模块中具有STACK属性的同名段连接成一个大的堆栈段,连接后的堆栈空间是连接前各模块预留的堆栈空间之和。程序装入后,DOS自动初始化SS和SP,使SS的内容为堆栈段的段基址,SP的内容为堆栈空间的字节数,使SS:SP自动指向栈顶。连接程序要求.EXE文件的汇编源程序必须有堆栈段,否则连接时将发出警告信息:Warning no stack segmemt,但并不表示源程序有错误,只是提醒用户注意。AT表达式:表示本段可定位在表达式所指示的节边界上。(3)字长选择字长选择用于定义段中使用的偏移地址和寄存器的字长。有两种字长可供选择。USE16:段字长为16位,最大段长为64KB;USE32:段字长为32位,最大段长为4GB。若字长选择缺省,确认为USE32。(4)类别名类别名表示逻辑段的类别,类别名是用户定义的,必须用单引号括起来,长度不超过40个字符。类别名是可选项。习惯上,数据段的类别名用DATA,代码段的类别名用CODE,堆栈段的类别名为STACK。连接程序把不同模块中类别名相同的同名段组织成一类,放在相邻的存储区中。3段分配伪指令格式:ASSUME段寄存器名:段名,段寄存器名:段名,。功能:该语句通知汇编程序源程序中定义的段由那个段寄存器寻址。段寄存器可以是、CS、DS、ES、SS、FS和GS。说明:(1)格式中,ASSUME是伪指令名,是语句中的关键字,不可缺省。段寄存器后面必须有冒号,如果分配的段名不止一个,则应用逗号分开。段名是指用SEGMENT/ENDS伪指令定义过的段名。ASSUME语句是非执行语句,要求放在代码段内段定义语句之后。(2)ASSUME语句仅仅约定了对逻辑段进行寻址操作时使用哪个段寄存器,而段寄存器的初值还必须在程序中用指令设置。例如用以下两条语句可以设置数据段寄存器的初值,设DATA为数据段名:使用SEG运算符求出段基址,然后装入DS段寄存器。例如:MOVAX,SEG DATAMOVDS,AX直接把段名赋给段寄存器,例如: MOVAX,DATAMOVDS,AX(3)DOS把一个可执行的程序(EXE文件)调入内存之后,自动地把程序代码段的基址赋给了CS,也就是说,对CS的赋值是由DOS系统自动完成的,程序员不能干预。433其它伪指令在汇编语言中,为了指示程序中指令和数据在相应段中的偏移地址,可使用定位伪指令和当前位置计数器。1定位伪指令格式:ORG表达式ORG伪指令用来指定该语句之后的程序段或数据块的起始地址的偏移地址。例如:ORG 1000H;ADD1变量的偏移地址从1000H开始ADD1DB2,3,45HORG1020HADD2DW0080H,0098H;变量ADD2的偏移地址从1020H开始通常ORG伪指令可以出现在程序的任何位置上。2当前位置计数器$在汇编语言中,可以用$表示当前位置计数器的现行值。例420DATASEGMENTSEGDBWELCOMECOUNTEQU$SEGDATAENDS其中,$表示当前的偏移地址,SEG表示上一条语句中变量SEG的偏移地址,$SEG表示两个偏移地址之差,正好是以变量SEG为首地址的连续字节数,即SEG为首地址的字符个数。3 程序结束伪指令ENDEND伪指令作为汇编语言源程序的结束语句,一般放在源程序的最后一行。一个程序模块只允许有一个END语句。格式:END标号其中,标号是该程序中的第一条可执行语句的标号。44汇编语言程序设计的方法程序有顺序、循环、分支和子程序四种基本结构形式。顺序结构程序是指完全按照指令排列的顺序逐条执行的程序,这是最常见的也是最简单的一种结构形式。在程序设计中,单纯一种结构的程序并不多见,大多数都是多种结构的组合。本节主要举例说明分支、循环和子程序的程序设计方法。441分支程序设计分支程序可以用转移指令实现也可以用MASM6.X的伪指令实现。1用转移指令实现分支用条件转移指令实现分支时,条件转移指令通常安排在比较指令、加减指令和逻辑运算指令后面使用,根据标志寄存器的状态,决定是否转移。例421把连续存放在DAT中的三个数,按递减顺序排列。分析:为了实现递减排列,可以对三个数两两进行比较,比较后的大数放在前面。程序流程图如图4.3所示。 图4.3 三数排序流程图程序如下:.MODELSMALL.486.STACK.DATADAT DW-36,64,125.CODE.STARTUPMOVBX,OFFSETDATMOVAX,BXCMPAX,BX+2JGENEXT1;AB?XCHGAX,BX+2;交换A,BMOVBX,AXNEXT1:MOVAX,BX+2CMPAX,BX+4JGENEXT2;BC?XCHGAX,BX+4;交换B,CMOVBX+2,AXNEXT2:CMPBX,AXJGENEXT3;AB?XCHGBX,AX;交换A,BMOVBX+2,AXNEXT3:.EXIT0END2用MASM6.X的伪指令实现分支MASM6.X引入了条件控制伪指令,类似于高级语言中分支语句的相应功能。这些伪指令在汇编时自动展开,生成相应的比较和条件转移指令序列,实现分支结构,简化了分支结构的编程。分支语句主要用.IF伪指令来实现,条件控制格式如下:.IF条件表达式;条件成立(表达式的值非0),执行语句1语句1.ELSE IF条件表达式;前面IF条件不成立(值为0),并且当前ELSEIF条;件为真,执行语句2语句2.ELSE;前面IF条件不成立,执行语句n语句n.ENDIF;分支结束其中方括号部分为可选。条件表达式允许的操作符及功能说明如下:= =等于!=不等于大于=大于等于小于=A&AL=a&A=fSUBAL,57H.ELSESUBAL,30H.ENDIF.EXITEND442循环程序设计在程序设计中,常常有一段程序需要反复执行若干次,这通常用循环的方法来实现。循环结构是根据某一条件成立与不成立重复执行循环体。循环结构程序通常由四个部分组成:循环初始部分、循环工作部分、修改部分和循环控制部分。循环初始部分是循环开始的必要准备,如设置循环次数、设置地址指针和地址计数器、设置常数和寄存器清0等。循环工作部分是重复执行的程序代码。可以是顺序结构、分支结构或循环结构的程序段。修改部分是对循环条件的修改,为执行下一次循环做准备。循环控制部分判断循环条件是否满足,循环是否继续执行。根据循环控制部分在程序中的位置不同,分为“先循环,后判断”和“先判断,后循环”两种结构。图4.4是两种循环程序的结构。 图4.4循环程序的结构循环程序可以用循环指令实现还可以MASM6.X的循环伪指令实现。1.用循环指令实现循环结构借助于80X86循环控制指令,如:LOOP、LOOPE、LOOPNE、JCXZ以及重复操作前缀REP、REPE、REPNE等,可以方便地实现循环。例4.23从键盘输入20个字符,按键入次序寻找字母顺序最大的字符,并且显示输出(区别大小写)。分析:大写字符AZ的ASCII码为41H5AH,小写字母az的ASCII码为61H7AH,大小写字母的ASCII码值相差20H,因此在判断ASCII码值的大小写时,小写字符ASCII码减去20H参与比较。程序流程如图4.5所示。 图4.5 例423程序流程图程序如下:.MODEL SMALL.DATABUFDB21,?,21DUP(?)BLOCKDB0AH,0DH,?,$.CODE.STARTUPMOVDX,OFFSETBUF;键入字符MOVAH,0AHINT 21HLEABX,BUF+2MOVCX,BUF+1MOVAL,BX;缓冲区第一个字符送ALANDAL,B;小写字母ASCII码减20HMOVSI,BX;缓冲区第一个字符地址送SIAGAIN:INCBXMOVDL,BX;缓冲区字符送DLANDDL,BCMPAL,DL;比较两字符大小JAENEXTXCHGAL,DL;大数存AL中MOVSI,BX;大数地址送SINEXT:LOOPAGAINMOVDL,SI;最大字符送DLMOVBLOCK+2,DLMOVDX,OFFSET BLOCK;显示输出MOVAH,9INT21H.EXITEND例424将内存首地址为BLOCK开始的10个带符号的字节数按由小到大的次序排列。程序流程如图4.6所示。Incount为内循环变量,excount为外循环变量。 图4.6例424程序流程如图程序如下:.MODELSMALL.DATABLOCKDB66H,88H,33H,22H,00H,40H,50H,60H,70H,80H.CODE.STARTUPMOVDI,9;循环次数送DILOOP1:MOVCX,DI;设置循环次数MOVBX,0LOOP2:MOVAL,BLOC

温馨提示

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

评论

0/150

提交评论