【文档说明】第4章汇编语言与源程序结构汇总课件.ppt,共(57)页,193.927 KB,由小橙橙上传
转载请保留链接:https://www.ichengzhen.cn/view-44754.html
以下为本文档部分文字说明:
第4章汇编语言与源程序结构汇总4.1汇编语言源程序与汇编程序1、汇编语言源程序汇编语言源程序是用汇编语言编写的程序,简称汇编语言程序。汇编语言程序通过编辑程序在计算机中建立汇编语言源程序文件(ASM文件)。2、汇编程序将汇编语言源程序编译
成目标程序的加工程序称为汇编程序。这一加工过程称为汇编。汇编程序的作用就是把源程序文件(ASM文件)转换成用二进制代码表示的目标程序文件(OBJ文件)。汇编程序的主要功能有:①检查源程序。②测出源程序语法错误,并给出错误。③产生目标程序,并可给出列表文件④展开宏指令。返回汇编语言程序的开
发过程编辑文本编辑器,如EDIT.COM源程序:文件名.asm汇编汇编程序,如TASM.EXE目标模块:文件名.obj连接连接程序,如TLINK.EXE可执行文件:文件名.exe调试调试程序,如DEBUG.EXE应用程序错误错误错误错误•完整的汇编语言源程序由段组成•一
个汇编语言源程序可以包含若干个代码段、数据段、附加段或堆栈段,段与段之间的顺序可随意排列•需独立运行的程序必须包含一个代码段,并指示程序执行的起始点,一个程序只有一个起始点•所有的可执行性语句必须位于某一个代码段内,说明性语句可根据需要位于任一段内•通常,程序还
需要一个堆栈段一个完整的汇编程序•stacksegmentstack;定义堆栈段•dw512dup(?)•;堆栈段有512字(1024字节)空间•stackends;堆栈段结束•datasegment;定义数据段•stringdb’Hello,Everybody!’,0dh,0ah
,’$’•dataends•codesegment’code’;定义代码段•assumecs:code,ds:data,ss:stack•start:movax,data;建立DS段地址•movds,ax••movdx,of
fsetstring•movah,9•int21h•movax,4c00h•int21h;利用功能调用返回DOS•codeends;代码段结束•endstart•;汇编结束,同时指明程序起始点•stacksegmentstack•dw512
dup(?)•stackends•datasegment•...;在数据段定义数据•dataends•codesegment’code’•assumecs:code,ds:data,ss:stack•start:movax,data•movds,ax•..
.;在代码段填入指令序列•movax,4c00h•int21h•...;子程序代码•codeends•endstart4.2汇编语言语句种类及其格式语句是汇编语言源程序的基本组成单位。一个汇编语言源程序中有3种基本语句:指令语句:产生机器代码,再程序运行时完成伪指令语句:提供控
制信息.入分配存储区,定义各种符号.不产生目标代码.汇编时完成宏指令语句:将多次重复使用的程序段命一个名字前两种是最常见、最基本的语句。指令语句和伪指令语句不仅在程序中的功能不同,而且实现其功能的方法和时间
也是不同的。语句的格式指令语句就是计算机中指令系统的各条指令,每条指令语句在汇编时都产生一个供CPU执行的机器目标代码,所以这种语句又称为可执行语句。计算机中每条指令语句表示一种基本功能,这些基本功能是在程序运行期间由计算机
硬件来实现的。一条指令语句由四个字段组成,其一般格式如下:[标号:]指令助记符[操作数][;注释](1)标号标号是指令语句的符号地址,它代表指令代码存放地址的第一个字节地址。标号是指令语句的可选项,通常在一个程序段或子程序的入口指令
语句选用标号,当程序需要转入这个程序段或调用子程序时,就可直接引用这标号。标号通常在代码段中定义,后面跟冒号‚:‛,它经常在转移指令或CALL指令中引用,用以表示转向地址,引用时标号后不跟冒号。(2)指令助记符指令助记符
为指令语句的核心,是不可省略的主要部分,如MOV、ADD、XOR、RCL等等,它表示指令语句要求CPU完成的具体操作。(3)操作数操作数表示指令助记符的操作对象,不同的指令所带的操作数不同,有一个操作数的指令(如INC、NOT等),有二个操作数的指令(如ADD、
XOR等),无操作数指令(如CLC、STD等)。若需要操作数,则每一个操作数要依据寻址方式来表示。操作数可以是常数、寄存器、标号、变量和表达式。(4)注释注释是用来说明一段程序或一条或多条指令的功能,它是可选项,注释均以分号‚;‛开始,它可占一行或多行
。注释还通常用于调试程序。注释是语句的非执行部分,因此,它不出现在机器目标代码中,也不影响指令语句的功能。2、伪指令语句伪指令语句指示汇编程序在汇编源程序时完成某些工作,比如完成数据定义、分配存储区、指示程序
结束等。伪指令属于汇编控制命令,它所指示的操作是由汇编程序在汇编源程序时完成的,在汇编时,它不产生目标代码,在将源程序汇编成目标程序后,它就不复存在了。综上所述可知,伪指令语句与指令语句的主要区别是:伪指令语
句经汇编后不产生机器目标代码,而指令语句经汇编后将产生相应的机器目标代码;伪指令语句所指示的操作是在程序汇编时完成的,而指令语句的操作必须在程序运行时才能完成。一条伪指令语句也由四个字段组成,其一般格式如下:[符号名]
伪指令符操作数[;注释](1)符号名符号名在伪指令语句中是一个可选项,符号名后面没有冒号,符号名可以是常量名、变量名、过程名等。(2)伪指令符伪指令符指定汇编程序要完成的具体操作,它是伪指令语句的核心部分,如数据定义伪指令DB、DW、
DD,段定义伪指令SEGMENT,定义过程伪指令PROC等等。(3)操作数伪指令中的操作数可以是常数、字符串、变量、表达式,其个数由具体的伪指令决定,各个操作数之间用‚,‛分隔。(4)注释伪指令语句的注释也是可选项,需要时
必须以‚;‛开始。3、标识符指令语句中的标号和伪指令语句中的符号名统称为标识符。它们由若干字符组成,标识符的组成规则如下:(1)一个标识符由1--3个字符组成。(2)组成标识符的字符可以是字母(A--Z或a--z)、数字(0--9)、专用字符(‚?‛、‚·‛、‚@‛
、‚$‛、‚下划线_‛)。(3)除数字外,上述其余字符均可作为标识符的首字符,‚·‛只能作为标识符的首字符。(4)不能使用属于系统的专用保留字。返回4.3汇编语言数据与运算符汇编语言的指令语句和伪指令语句操作数一般为常量、变量、标
号、表达式。1、常量常量是没有任何属性的纯数值,它的值在汇编期间已能完全确定,且在程序运行中也不会发生变化。常量分为数值常量、字符串常量和符号常量,它主要用于指令语句中的立即数或伪指令语句中给变量赋初值等。•它又分成多种形式:•(1)十进制常数•(2)十六进制常数•(3)二进
制常数•(4)八进制常数•常数(常量)表示一个固定的数值,大小写不敏感•各种进制的数据以后缀字母区分,默认不加后缀字母的是十进制数(5)字符串常量字符串常量是用单引号括起来的一个字符或多个字符。字符串常量以单引号中各字符的ASCII码形式存储在内存中,如‘H’,在内存中就是41H,‘12’就是
31H,32H。使用时可在单引号内直接写字符序列,如‘12AB’,也可写字符的ASCII码,ASCII码之间用逗号分隔(此时不需要用单引号),如31H,32H,41H,42H表示字符串‘12AB’。(6)符号常量符号常量是指用EQU伪指令或赋值语句‚=‛定义过的符号名,可作操作数项或在表达式
中使用。常数若使用有意义的符号名来表示,可以提高程序的可读性,同时更具有通用性2、变量在汇编语言中,变量是一个数据存储单元的名称,即数据存放地址的符号表示。它代表存放在某些存储单元的数据,这些数据在程序运行期间随时可以改变。为方便访问变量,在程序中通过变量名来使用变量。变量的属性由于
存储器是分段使用的,因而源程序定义的变量具有3个属性:(a)段属性(SEG)变量的段属性是指定义变量时它所在段的段首地址。(b)偏移属性(OFFSET)变量的偏移属性是指所在段的段首地址到定义该变量的位置之间的字节数(即偏移地址)。上述的段属性和偏移属性值就构成了一个变量的逻辑地址。(
c)类型属性(TYPE)变量的类型属性表示存储变量时所占存储单元的字节个数。3、标号标号是一条指令语句的符号地址,在汇编源程序中,只有在需要转向一条指令语句时,才为该指令语句设置标号,以便在控制转移指令中直接引用这个标号。标号一般在代码段中定义和引用。由于标号代表了指令的符号地址,所
以标号也有3个属性:(a)段属性(SEG)。标号的段属性是指标号定义所在段的段首地址。(b)偏移属性(OFFSET)。标号的偏移属性是指标号所在段的段首地址到该标号的字节距离。(c)类型属性(TYPE)。标号的类型属性表示了它的转移特
性,即该标号是作为段内还是段间转移(或调用)指令的目标地址。标号的类型属性有2种:NEAR类型和FAR类型。4、表达式和运算符汇编语言的指令语句和伪指令语句中,表达式是操作数项的常见形式,表达式是由常量、变量、标号用运算符连接而成有意义的式子。表达式分为数
值表达式和地址表达式,任一表达式的值只计算一次,表达式的计算是在源程序汇编过程中进行的,而不是在程序运行中进行的,汇编程序将表达式计算后得到一个数值或一个地址。在8086汇编语言中,运算符分为:算术运算符、逻辑运算符
、关系运算符、数值返回运算符、属性运算符和字节分离运算符。运算符–算术运算符•+-*/MOD–逻辑运算符•ANDORXORNOT–移位运算符•SHLSHR–关系运算符•EQNEGTLTGELE算术运算符•实现加、减、乘、除、取余的算术运算•movax,3*4+5;等价于movax,1
7•其中MOD也称为取模,它产生除法之后的余数,如19mod7=5•加+和减-运算符还可以用于地址表达式•除加、减外,其他运算符的参数必须是整数逻辑运算符•实现按位相与、相或、异或、求反的逻辑运算•oral,03hAND45h•;等价于
oral,01h移位运算符•实现对数值的左移、右移的逻辑操作;移入低位或高位的是0•格式为:•数值表达式SHL/SHR移位次数•moval,0101bSHL(2*2)•;等价于moval,01010000b关系运算符•用于比较和测试符号数值•MASM用0FFFFH(补码-1)表示条件为真•MASM
用0000H表示条件为假–movbx,((PORTLT5)AND20)OR((PORTGE5)AND30)•;当PORT<5时,汇编结果为movbx,20•;否则,汇编结果为movbx,30(1)数值表达式数值表达式是由常量与
算术运算符、逻辑运算符或关系运算符构成的有意义的式子。数值表达式在汇编期间进行运算,运算结果为一数值常量,它只有大小而没有属性。(2)地址表达式地址表达式是由常量、变量、标号、寄存器(BX、BP、SI、DI
)内容(用寄存器名加方括号表示)和运算符组成的有意义的式子。单个的变量、标号、寄存器的内容是地址表达式的特例。地址表达式中可以使用算术运算符中的‚+‛、‚-‛运算符和关系运算符。在地址表达式中,常用的形式是:变量±常量
。地址表达式除使用数值表达式的运算符外,还可以使用特殊算符。(a)属性运算符属性运算符主要用于临时修改变量、标号或某个内存单元中的操作数的类型属性。①段超越前缀‚:‛。其格式为:段寄存器名:地址表达式或段名:地址表达式②类型运算符PTR。其使用格式为:类型PTR地址表达式根据地址表达式的不
同值,类型可以是BYTE、WORD、DWORD、NEAR、FAR等。③定义类型运算符THIS。其格式为:标识符EQUTHIS类型(b)数值返回运算符数值返回运算符有5种,这些运算符的运算对象必须是变量或标号,其功能是分离出变量或标号的段、偏移地址及类型的属性值,运算结果为一数值常量。①SEG运算符
格式:SEG变量或标号功能:分离出其后变量或标号所在段的段首地址。②OFFSET运算符格式:OFFSET变量或标号功能:分离出其后变量或标号的偏移地址。③TYPE运算符格式:TYPE变量或标号功能:分离出其后变量或标号的
类型值。④LENGTH运算符格式:LENGTH变量功能:取出变量所含的数据存储单元个数。该运算符只对变量起作用,它的取值根据定义该变量时数据定义伪指令后面第一个表达式的形式而定。如果第一个表达式为重复子句‚nDUP(表达式)
‛的形式,则取值为前面的重复因子n。如果为其它形式的表达式,则取值均为1。⑤SIZE运算符格式:SIZE变量功能:取出变量所含的数据存储区的总字节数。其返回值为该变量的LENGTH值和TYPE值的乘积,即:LENGTH变量*YTPE变
量。(c)分离运算符①分离高字节运算符HIGH。格式:HIGH常量或地址表达式功能:用来分离出其后16位常量或地址表达式的偏移地址的高字节。②分离低字节运算符LOW。格式:LOW常量或地址表达式功能:用来
分离出其后16位常量或地址表达式的偏移地址的低字节。movah,HIGH8765h;等价于movah,87h(d)其他运算符SHORT运算符:用于说明其后的标号在短距离(-128--27之间)内。()运算符用于改变运算的优先级别。[]运算符用于表示间接寻址。返回4.4伪指令伪指令又称为伪操作,伪
指令是汇编语言程序设计的一个重要部分,由于汇编程序在汇编过程中无法区分源程序中的分段情况,哪些是数据,哪些是指令,也无法识别数据的类型,以及源程序在哪结束,因此,80X86宏汇编语言提供了多种伪指令,它主要告诉汇编程序如何正确地将汇编源程序汇编成目标程序。
1、符号定义伪指令符号定义伪指令用于为程序中多次出现的同一个常量或表达式定义为一个标识符,以便在源程序中以标识符来代替对应的常量或表达式。符号定义伪指令有以下两种。(1)等价伪指令EQU格式:符号名EQU表达式功能:为常量
或表达式及其它各种符号定义一个等价的符号名,但它不申请分配存储单元。说明:①表达式可以是常量或数值表达式;地址表达式;变量、标号或指令助记符。②符号名不占存储单元,没有段、偏移和类型3种属性③在同一源
程序中,使用EQU定义的符号不能与本程序中的其它符号名同名;另外,同一符号不能用EQU伪指令重新定义。EQU伪指令主要有以下3方面应用:①定义符号常量。用符号名表示常量、数值表达式。②EQU与属性运算符PTR或THIS连用,可以给变量或标
号定义新的类型属性并重新命名。但其段属性和偏移属性不变。③利用EQU可以用一个符号名替代一个复杂的地址表达式和其它一些符号,如指令助记符、变量名、标号、段名、寄存器名、宏定义名等。(2)等号伪指令格式:符号名=表达式功能:该语句的功能与EQU语句类似,不同的是等号伪
指令能对所定义的符号名多次重新定义,且以最后一次定义的值为准。•字变量和字常量的定义:•WNUMEQU5678H;定义WNUM为常量•COUNTDW20H•;定义COUNT变量,假设在数据段的偏移地址为10H•字变量和字常量的应用:•MOVAX,[BX+SI+WNUM];MOVAX,[BX+S
I+5678H]•MOVAX,COUNT;MOVAX,[0010H]•MOVAX,[SI+COUNT];MOVAX,COUNT[SI]•;MOVAX,[SI+10H]•LEABX,COUNT;LEABX,[0010H]•MOV
BX,OFFSETCOUNT;MOVBX,0010H1、数据定义伪指令常用的数据定义伪指令有DB、DW、DD、DQ、DT。格式:[变量]数据定义伪指令表达式[,表达式,…]功能:定义数据存储区,类型由数据定义伪指令确定,初值由表达式给定。•变量名为用户自定义标识符,表示初
值表首元素的逻辑地址;用这个符号表示地址,常称为符号地址•变量名可以没有。这种情况,汇编程序将直接为初值表分配空间,无符号地址•设置变量名是为了方便存取它指示的存储单元•初值表是用逗号分隔的参数–主要由数值常数、表达式或?、DUP组成
–?——表示初值不确定,即未赋初值;–DUP——表示重复初值–DUP的格式为:–重复次数DUP(重复参数)•变量定义伪指令根据申请的主存空间单位分类•DB——定义字节伪指令•DW——定义字伪指令•DD——定义双字伪指令•DF——定义3字伪指令•DQ——定
义4字伪指令•DT——定义10字节伪指令•DB伪指令用于分配一个或多个字节单元,并可以将它们初始化为指定值•初值表中每个数据一定是字节量(Byte),存放一个8位数据:•可以是0~255的无符号数•或是-128~+127带符号数•也可以是
字符串常数datasegment;数据段Xdb'a',-5db2dup(100),?Ydb'ABC'dataends•moval,X•;此处X表示它的第1个数据,故AL←'a'•decX+1•;对X为始的第2个数据
减1,故成为-6•movY,al•;现在Y这个字符串成为'aBC'定义字单元伪指令DW•DW伪指令用于分配一个或多个字单元,并可以将它们初始化为指定值•初值表中每个数据一定是字量(Word),一个字单元可用于存放任何16位数据
:•一个段地址•一个偏移地址•两个字符•0~65535之间的无符号数•-32768~+32767之间的带符号数datasegment;数据段countdw8000h,?,'AB'maxintequ64hn
umberdwmaxintarraydwmaxintdup(0)dataends定义双字单元伪指令DD•DD伪指令用于分配一个或多个双字单元,并可以将它们初始化为指定值•初值表中每个数据是一个32位的双字量(Doubl
eWord):•可以是有符号或无符号的32位整数•也可以用来表达16位段地址(高位字)和16位的偏移地址(低位字)的远指针•varddDD0,?,12345678h•farpointDD00400078h其他数据单元定义伪指令•定义3字伪指令DF——用于为一个或多个6字节变
量分配空间及初始化•6字节常用在32位CPU中表示一个48位远指针(16位段选择器:32位偏移地址)•定义4字伪指令DQ——用于为一个或多个8字节变量分配空间及初始化•8字节变量可以表达一个64位整数•定义10字节伪指令DT——用于为一个或多个10字节变量分配空间及初始化•
10字节变量可以表达扩展精度浮点数3、段结构伪指令编制一个80X86汇编语言源程序,段是基础,这有两方面含义:一是必须按段来构造程序,二是在程序执行时,要凭借四个段寄存器对各个段的存储单元进行访问。段结构伪指令主要有两条语句
,即段定义伪指令和假定伪指令。(1)段定义伪指令SEGMENT/ENDS格式:段名SEGMENT[定位类型][组合类型][‘类别’]┇段体段名ENDS功能:定义一个逻辑段,指定段的名字和范围,段在内存中的起始位置、段与段之间
的连接关系。说明:①段名由用户指定,开始与结束的段名须一致。②SEGMENT/ENDS伪指令把程序分成若干逻辑段。③删节号为段体,段体内为指令和伪指令序列。(2)假定伪指令ASSUME假定伪指令主要用于指示汇编程序哪些段是当前段以及这些段与段寄存器之间的对应关
系。格式:ASSUME段寄存器名:段名[,段寄存器名:段名,…]其中,段名是指用SEGMENT/ENDS语句已定义的段名,也可以是表达式‚SEG变量或标号‛,或者是关键字NOTHING;段寄存器名可为CS、DS、SS、ES四者之一。功能:该
语句一般出现在代码段中,用来设定段寄存器与段之间的对应关系,以便汇编程序知道段的结构和在执行各种指令时知道应访问哪个段;也可用来取消段寄存器与段之间的对应关系(使用NOTHING时)。说明:①ASSUME伪指令设置在
代码段内,第一个ASSUME语句一般放在段定义语句之后,是说明性语句。②在一个代码段中,如果没有另外的ASSUME伪指令重新设置,原有ASSUME语句的设置一直有效。③不在当前段中的变量和数据存储单元均是不可访问的,否则,会在汇编
时产生错误或运行时造成混乱,产生逻辑上的错误,得出错误结果。④ASSUME伪指令不产生任何目标代码,它仅仅是告诉汇编程序,哪些段是当前段,而且它们分别由哪个段寄存器指向。⑤汇编程序不能检查在程序运行期间段寄存器内容是否与上述ASSUME语句的设置一致。如果在程序中间用ASSUME语
句重建了DS或ES与某段的关系时,就一定要紧跟着将这个新段首地址送入DS或ES中,否则,会因段寄存器的内容未更改而使得后面数据的读写仍在原来的数据段中进行,这样的错误,系统是检查不出来的,即出现逻辑错误。4、源程序开始和结束伪指令(1)源程序开始伪指令在源程序开始处
可以用NAME或TITLE为模块取名字。①NAME伪指令格式:NAME模块名汇编程序将以给出的‚模块名‛作为模块的名字。②TITLE伪指令如果程序中没有NAME伪指令,则也可使用TITLE伪指令。格式:TITLEtextTITLE伪指令可
指定每一页上打印的标题。同时,若程序中没有NAME伪指令,则汇编程序将用text中的前6个字符作为模块名。text最多可有60个字符。若程序中既无NAME又无TITLE伪指令,则将用源程序名作为模块名。所以N
AME及TITLE伪指令并不是必要的,但一般常使用TITLE,以便在列表文件中能打印出标题来。(2)源程序结束伪指令格式:END[地址表达式]功能:该语句为源程序的最后一个语句,用以标志整个程序的结束,即告诉汇编程序汇编工作到此结束。其中,地址表达式为可选项,若选用地址表达式,则表示此程序是主程序
,它可以单独执行,其地址表达式为该程序的启动地址,即程序开始运行的第一条指令的地址,例如,‚ENDSTART”,此START是第一条指令的标号;若不选用表达式,则说明此程序为一子程序,不能单独运行,只能被其它程序调用。5、定位伪指令ORG与汇编地址计数器($)汇编程序在汇编源程序时,每遇到一
新段,就为该段设置一个初值为0的汇编地址计数器,汇编程序使用汇编地址计数器记载正在汇编的数据或指令的目标代码在当前段内的偏移地址。当前汇编地址计数器的值可用符号$表示,用户可在程序中直接使用$,表示引用当前汇编
地址计数器的值。例如:ARRAYDW4000H,5000H,6000HCOUNTEQU($-ARRAY)/2•汇编地址计数器的值可以用定位伪指令ORG设置。•ORG伪指令格式:ORG数值表达式•功能:将数值表达式的值赋给汇编地
址计数器。•ORG100h;从100h处安排数据或程序•ORG$+10•;使偏移地址加10,即跳过10个字节空间6、过程定义伪指令PROC/ENDP在程序设计中,常把具有某种功能的程序段设计成一个过程。80X86宏汇编语言用于过程定义的伪指令的格式为:过程名PROC[NEAR或
FAR]┆;过程体过程名ENDP其中过程名是过程入口地址的符号表示,它由程序员指定,且开始处和结束处的过程名一致。过程名同标号一样,具有三种属性:段属性、偏移属性和类型属性,类型属性可指定为NEAR或FAR两种。具有NEAR属性的子程序与调用程序应在同一个逻
辑段中,而具有FAR属性的子程序和调用程序不在同一个逻辑段内。即段内调用的子程序一般为NEAR类型,段间调用的子程序一般为FAR类型,若为NEAR类型,定义过程时,参数NEAR可省略。过程体为过程内的指令和伪指令序列。返回4.5源
程序结构模式一个汇编源程序一般由几个段组成,其中,必不可少的是代码段和堆栈段,堆栈段也可以不用显示定义,可以直接使用隐式堆栈段,如果程序中需要使用数据存储区,还要定义数据段,必要时还要定义附加段。一般情况下,对于不太复杂的程序只需要三个段(即数据段、堆栈段和代码段)就可以了,而对于复杂的程
序,除了使用上述三个段以外还可以使用多个段,甚至可以使用多个程序模块。用INT21H返回DOS的程序结构模式INT21H是DOS系统功能调用,用这种方法返回DOS的程序结构比较简单,我们编写程序常采用此结构,具体编写时只要在用户程序的最后安排
两条指令即可,即:MOVAH,4CHINT21H返回简化段定义格式MASM6.x支持•;SampleA.ASM•.modelsmall•.stack•.data•...;在数据段定义数据•.code•.startup•...;在代码段填入指令序列•.exit0•
...;子程序代码•end•stacksegmentstack•dw512dup(?)•stackends•datasegment•...;在数据段定义数据•dataends•codesegment’code’•assumecs:co
de,ds:data,ss:stack•start:movax,data•movds,ax•...;在代码段填入指令序列•movax,4c00h•int21h•...;子程序代码•codeends•endstart