1第4章汇编语言程序设计movax,12hcalldisplayJmp1234h2主要内容:汇编语言源程序的结构汇编语言语句格式伪指令系统功能调用汇编语言程序设计34.1汇编语言源程序几个概念:机器语言——二进制数形式的指令和数据。–例如:B064–能够被CPU直接识别和执行。但不直观、不易理解和记忆。助记符——用便于记忆的英文单词表示的指令操作码。它反映了指令的功能和主要特征,便于人们理解和记忆。–例如:MOVAL,64H–不能被CPU直接识别和执行。但容易理解和记忆。4例:LP1:MOVAX,VAR…LOOPLP1汇编语言——指令助记符、符号、名字、标号、伪指令等语言元素的集合及其使用规则。用汇编语言编写的程序称为汇编语言源程序。符号和标号——指令的操作数可能放在存储器中,这就需要指定操作数的地址。程序中遇到转移指令或调用指令,也需要指定转移地址。但是程序中使用具体地址很不方便,出现错误时修改也很麻烦。所以往往采用符号(名字)或标号来表示地址。5汇编程序——汇编语言源程序需翻译成机器语言目标程序,计算机才能执行。这个翻译过程称为汇编。执行翻译的程序称为“汇编程序”。执行翻译操作汇编程序汇编语言源程序机器语言目标程序输入输出MASMTASMMASM32…6汇编语言程序设计与执行过程输入源程序源文件(.ASM)汇编(翻译)目标文件(.OBJ)链接可执行文件(.EXE)调试最终程序(.EXE)74.1.1汇编语言源程序的结构汇编语言源程序通常由一个或多个程序模块组成,每个模块一般包括三个逻辑段:·数据段——存放数据、变量·堆栈段——堆栈区域·代码段——存放程序指令汇编语言源程序的程序框架结构8一个基本的汇编语言程序框架如下:stackSEGMENTPARA‘stack’DB100DUP(‘stack’)stackENDSdataSEGMENT数据、变量在此定义dataENDScodeSEGMENTASSUMECS:code,DS:data,ES:datastart:MOVAX,dataMOVDS,AXMOVES,AX此处加入你自己的程序段MOVAH,4CHINT21HcodeENDSENDstart堆栈段数据段代码段94.1.2汇编语言的语句与格式汇编语言的语句有两种:指令性语句——由8086指令助记符构成的语句指示性语句——由伪指令构成的语句指令性语句的格式为:标号:指令助记符目的操作数,源操作数;注释指示性语句的格式为:名字伪指令操作数1,操作数2,…,操作数n;注释注:各部分之间至少要用一个空格作为分隔符。10指令性语句由CPU执行,每一条指令性语句都有一条机器码指令与其对应。指令性语句汇编时生成机器码指示性语句由汇编程序执行。它告诉汇编程序应如何对源程序进行汇编,如何定义变量、分配存储单元以及指示程序开始和结束等。指示性语句无机器码指令与其相对应。指示性语句汇编时不生成机器码11语句的构成元素:标号——指令的符号地址,用来代表指令在存储器中的地址。只能出现在指令性语句中,标号后应加上冒号。名字——段、过程、变量的名字,用来代表它们在存储器中的地址。只能出现在指示性语句中,名字后不加冒号。指令助记符——8086助记符、伪指令操作数——指令的操作对象–对指令性语句——0,1,2个–对指示性语句——根据需要而定–操作数之间以逗号分隔–操作数可以是:寄存器、存储单元、常数或表达式例:AX,[DI+BX+10],200,16*8+num,等等12注释——以分号开头,可放在指令后,也可单独成一行。注意:注释应该写指令(段)在程序中的作用,而不要写指令本身的操作。例如:1)MOVCX,100;传送100到CX2)MOVCX,100;循环计数器置初值哪种写法更好?13第一个汇编语言程序:hello.asmdataSEGMENTHelloDB‘Hello,world!’,0DH,0AH,’$’dataENDSprogSEGMENTASSUMECS:prog,DS:datastart:MOVAX,dataMOVDS,AXLEADX,hello;取字符串首地址MOVAH,9INT21H;显示字符串MOVAH,4CHINT21H;退出程序progENDSENDstart名字标号144.1.3语句中的数据项与表达式数据项包括常量、变量、标号及表达式。1.常量二进制数,以B结尾。如01001101B。十进制数,如85。十六进制数,以H结尾。第1个数字为A-F时,前面应加0,如0F160H。字符串:用引号括起来的1个或多个字符。如‘ERROR!’,’a’,汇编时被翻译成对应的ASCII码45H,52H,52H,4FH,52H,21H和61H。15标号有三个属性:段地址:即标号所在段的段基地址;偏移量:标号所代表存储单元的段内偏移地址;类型:NEAR或FAR:NEAR—表示标号所在语句与引用标号的语句在同一码段内。FAR—标号所在语句与引用标号的语句不在同一代码段内。若引用时没有说明类型,默认为NEAR。标号在转移指令或CALL指令中作为转移地址被引用。2.标号——指令的符号地址16变量——即内存中的存储单元或数据区。变量名——存储单元(数据区)的符号地址或名字。变量也有三个属性:·段地址—变量所在段的段基地址;·偏移量—变量单元在段内的相对偏移量;·类型—变量的字节数。常用的有BYTE(1字节)、WORD(2字节)和DWORD(4字节)。变量在指令中作为存储器操作数被引用。3.变量17标号和变量名的使用规则–组成:A-Z(不分大小写)、0-9、?@._$–不能以数字开头,句号(.)只能作为首字符–长度小于31个字符–不能与保留字(指令助记符、伪指令、预定义符号等)重名–不能重复定义例如:正确:LP1、AGAIN、NEXT、_GO、OK_1错误:4M、LOOP、AAA、#HELP、+ONE184.表达式有数值表达式和地址表达式两种。数值表达式由常数与运算符构成。–在汇编时按优先规则计算出具体的数值,运行时不能改变。地址表达式由常数、寄存器、标号、变量与运算符构成。–对静态地址:地址表达式在汇编时进行计算;–对动态地址:地址表达式在运行时进行计算。表达式中的运算符有6类:算术、逻辑、关系、取地址、属性、杂类。19用于数值表达式,例:MOVAX,4*1024源操作数在汇编时被计算为4096,并替代原来的4*1024。用于地址表达式,例:LEASI,VAR+3若VAR的偏移地址为1000H,则VAR+3被汇编为[1003H]。即LEASI,[1003H]。1)算术运算符——+、-、*、/、MOD20逻辑运算符只能用于数值表达式中。例:MOVCL,36HAND0FH源操作数在汇编时计算得出06H,所以上述指令与”MOVCL,06H”等价。注意,不要把逻辑运算符与逻辑运算指令混淆:例:ANDAX,3FC0HAND0FF00H指令中第1个AND是操作符,第2个AND是运算符。2)逻辑运算符——AND、OR、XOR、NOT21关系运算的结果是一个逻辑值:真或假-若为“真”,则该值用全1表示;-若为“假”,则该值用全0表示。例:MOVBX,PORTGT300H若PORT的值大于300H,则指令汇编为:MOVBX,0FFFFH否则汇编为:MOVBX,03)关系运算符——EQ、NE、LT、GT、LE、GE22SEG:取变量/标号的段地址OFFSET:取变量/标号的偏移地址例:VARDB12H……MOVBX,OFFSETVAR;取变量VAR的偏移地址MOVAX,SEGVAR;取变量VAR的段地址注意:区别以下两条指令的异同:MOVBX,OFFSETVARLEABX,VAROFFSET运算符只能获取静态的偏移地址;LEA指令可获取静态或动态的的偏移地址。4)取地址运算符——SEG、OFFSET23TYPE:取变量的类型(字节=1,字=2,双字=4)LENGTH:取变量的长度(即变量中元素的个数)SIZE:取变量占用的字节数(=TYPE×LENGTH)例:语句“VARDW1,2,3,4,5”定义了一个字类型的变量,包含5个元素。MOVAL,TYPEVAR;AL=2MOVAL,LENGTHVAR;AL=5MOVAL,SIZEVAR;AL=105)取值运算符——TYPE、LENGTH、SIZE246)属性运算符——PTR用于指定地址操作数的类型。格式:类型PTR地址操作数类型∈{BYTE,WORD,DWORD,NEAR,FAR}BYTE、WORD、DWORD用于描述数据存储单元(变量)的地址。NEAR、FAR用于描述转移、调用的目的地址。25例:MOVBYTEPTR[DI],0;字节类型MOVWORDPTR[DI],0;字类型MOV[DI],0B5H;类型不定PTR也可用来进行强制类型转换例:STR1DW?;STR1定义为字类型MOVAX,STR1;合法MOVAL,STR1;非法MOVAL,BYTEPTRSTR1;合法264.2伪指令数据定义伪指令符号定义伪指令段定义和段寄存器指定伪指令过程定义伪指令结束伪指令由汇编程序执行的指令,它本身不被汇编成机器指令。常用的伪指令有:274.2.1数据定义伪指令用于定义变量,即内存单元或数据区。数据定义伪指令的格式为:变量名数据定义伪指令操作数,操作数,…常用的数据定义伪指令有如下几种:DB定义字节DW定义字DD定义双字操作数可以是常数、变量或表达式28例1:数据定义语句var1DB1,0AH,90H,10010111Bvar2DW1,0FFFFH,9ABCHvar3DD12345678H,0ABH其中:var1为字节类型的变量,有4个元素;var2为字类型的变量,有3个元素;var3为双字类型的变量,有2个元素。29·······································例2:定义三个变量如下DATA_BDB10,5,10HDATA_WDW100H,-4DATA_DDD0FFFBH汇编后的内存分配情况如右图所示。05H10H00H01HFCHFFHFBHFFH00H00H0AHQDATA_BDATA_WDATA_D10510H100H-40FFFBH存储器30例3:操作数可以是字符串,例如STRDB‘HELLO’汇编后的内存分配情况如下:注意下面两个定义的不同之处:DB‘AB’;41H在低字节,42H在高字节DW‘AB’;42H在低字节,41H在高字节STR‘H’‘E’‘L’‘L’‘O’48H45H4CH4CH4FH31若操作数为?,则表示只分配存储空间,但不赋初值。例4:ABCDB0,1,2,3,4,’OK’,’$’RSVDW?,?,?,?,?,?,?,?RSV只预留了8个字(16个字节)的存储空间。复制操作符DUP重复的数据可以使用复制操作符DUP,以简化书写。如上面的变量RSV也可写成:RSVDW8DUP(?)若操作数为$,则表示取汇编地址计数器的当前值。32例5:TABLEDB10DUP(?)BUFFERDWTABLE,$+3设TABLE的偏移地址为0080H,则汇编后的存储器分配情况如下图所示:TABLEBUFFER80H008AH008BH008CH008DH8FH00H00H0080H...0089H10Bytes.........334.2.2符号定义伪指令把一个表达式用一个符号表示,以后凡出现该表达式的地方都可用这个符号表示。类似于C语言中的#define。符号定义伪指令有两种:EQU,=用EQU定义的符号未清除前,不能重新定义。清除EQU定义可用PURGE伪指令。用”=”定义的符号允许重定义。注意:符号定义伪指令不分配存储空间,仅是给符号赋值!34例:FIVEEQU5COUNTEQUCXTENEQU10DIST=BYTEPTR[SI+BP]GOTO=JMP…MOVAX,TENMOVCX,COUNTADDDIST,FIVEDIST=WORDPT