《汇编语言伪指令参考.ppt》由会员分享,可在线阅读,更多相关《汇编语言伪指令参考.ppt(73页珍藏版)》请在三一办公上搜索。
1、第17章 汇编语言伪指令参考资料,17.1 存储器访问与指令运算符 17.2 汇编语言伪指令,17.1 存储器访问与指令运算符,17.1.1 存储器访问(寻址)对于存储器单元的访问,是通过存储器的单元地址来实现的。1.直接寻址 在存储器直接寻址时,指令中的一个操作数会指出一个已定义的变量名称,如下列的COUNTER:ADD CX,COUNTER,该指令执行时,微处理器把此变量的偏移地址加上数据段的(起始)地址来确定它在内存中的位置。2.间接寻址 存储器间接寻址时,操作数可选用基址寄存器(BX、BP)或变址寄存器(SI、DI),寄存器的内容就是操作数的偏移地址,使用常数、位移量及变量可使寻址变得
2、更灵活。用方括号表示间接寻址,并具有加号(+)的作用。其用法如下:,(1)使用基址寄存器BX时写成BX,默认段寄存器为DS;使用基址寄存器BP时写成BP,默认段寄存器为SS。例如,用BX的内容作为偏移地址(默认段寄存器为DS),将所指单元的内容传送到DX内:MOV DX,BX;基址寄存器(2)使用变址寄存器DI时写成DI,使用SI时写成SI,默认段寄存器均为DS。例如,用SI的内容作为偏移地址(默认段寄存器为DS),将所指单元的内容传送到AX内:MOV AX,SI;变址寄存器,(3)使用常数即把一个立即数或变量名放在方括号内。例如,将AX的内容传送到DS作为段地址,BX作为基址,SI作为变址加
3、上常数4所形成的逻辑地址单元内:MOV BX+SI+4,AX(4)配合变址寄存器“+”或“-”位移量。对于常数或位移只有极小的差别。例如,将以DS为数据段段地址,结合位移量8,DI变址寄存器,加上常数4所指的单元内容传送到AX内:MOV AX,8DI4;位移量+变址+常数,17.1.2 汇编语言指令运算符 汇编语言的运算符可分为属性运算符、返回值运算符,以及定义记录和结构的运算符等。本节先讨论前两类,定义记录和结构的运算符将在下节中讨论。1.LENGTH 运算符 LENGTH运算符返回DUP伪指令操作数所定义的数据项个数。下面的MOV指令将返回长度10给DX:TABLEA DW 10 DUP(
4、?).MOV DX,LENGTH TABLEA,若操作数中不含DUP项,则运算符返回值01。LENGTH的其他用法,另参考本节中的SIZE及TYPE。2.OFFSET 运算符 OFFSET运算符返回变量或标号的偏移地址(亦即数据段或指令段内的偏移地址)。其一般格式为:OFFSET 变量名(标号名),OFFSET 变量名(标号名)下面这条MOV指令返回TABLEA的偏移地址。请注意,LEA指令不使用OFFSET也会返回相同的值。MOV DX,OFFSET TABLEA LEA DX,TABLEA 上面这两条指令功能相同。,3.PTR运算符 PTR运算符用BYTE、WORD或DWORD来更改变量、
5、常数原先设定的类型(DB、DW或DD),并且用NEAR及FAR来更改标号原来隐含的距离属性。其一般格式为:New-type PTR 变量名(标号名)New-type字段放置所要赋予的新类型,如BYTE。下列为PTR运算符的例子:,FLDB DB22H DB35HFLDWDW 2672H;以7226存储 MOV AH,BYTE PTR FLDW;AH移入低字节(72)ADD BL,BYTE PTR FLDW+1;BL加入高字节(26)MOV BYTE PTR FLDW,05;将05移入低字节 MOV AX,WORD PTR FLDB;将双字节移入AX CALLFAR PTR DISPLAY;调用
6、段外子程序 另一个与PTR功能相似的是LABEL伪指令,将在下节说明。,4.SEG运算符 SEG运算符返回指定变量或标号所在的段地址。此运算符最常用在程序内把一些不同的汇编程序段结合起来。其一般格式为:SEG 变量名(标号名、段名、过程名、字段组名)下面两条MOV指令返回变量(FLDW)和标号(A20)所在段的段地址给DX:MOV DX,SEG FLDW;数据段地址 MOV DX,SEG A20;指令段地址,5.SHORT运算符 SHORT运算符的功能是,当JMP的目的地在-128+127字节之间时,用它来转变标号的属性为SHORT。其一般格式为:JMP SHORT 标号 汇编程序会把指令机器
7、码的操作数由双字节减少为单字节。这种特性在近距离向前转移时很有用,因为汇编程序并不知道转移位置的距离。,6.SIZE运算符 SIZE运算符返回变量的LENGTH和TYPE的乘积,而仅对变量含有DUP时有效。其一般格式为:SIZE 变量 请参阅TYPE运算符的例题。,7.TYPE运算符 TYPE运算符返回其作用对象变量所定义类型的字节个数。定义 字节数 DB 1 DW 2 DD 4 DQ 8 DT 10 STRUC由STRUC定义的字节数,NEAR 标号1(Hex FFFF)FAR 标号 2(Hex FFFE)其一般格式为:TYPE 变量名(标号名)下面的例子说明TYPE、LENGTH及SIZE
8、的使用。FLDBDB?TABLEADW20 DUP(?);定义20个字,MOV AX,TYPE FLDB;AX=0001MOV AX,TYPE TABLEA;AX=0002MOV CX,LENGTH TABLEA;CX=0014(20)MOV DX,SIZE TABLEA;DX=0028(40)因为TABLEA定义为DW,故TYPE返回0002,LENGTH根据DUP的定义返回Hex 0014(20),而SIZE返回TYPE与LENGTH的乘积,即Hex 28(40)。,17.2 汇编语言伪指令,1.ASSUME伪指令 ASSUME的功能是使汇编程序能将内存段与CS、DS、ES、SS等段寄存器
9、联系起来。其一般格式为:ASSUME 段寄存器名:name,.,name可为段名、段组名GROUP。一个ASSUME句中可以按任何顺序最多指定4个段寄存器,例如:ASSUME CS:CODESG,DS:DATASG,SS:STACK_,ES:DATASG 关键字NOTHING可以用来取消前面ASSUME所指定的某一个段寄存器,例如:ASSUME ES:NOTHING,假若没有指定DS寄存器或使用NOTHING取消了它,那么为了要存取数据段内的数据项时,就必须明确规定使指令操作数以DS寄存器为参考对象,即要指明操作数相应的段寄存器,例如:MOV AX,DS:BX;使用变址寻址 MOV AX,DS
10、:FLDW;传送FLDW的内容 当然,此时DS寄存器必须含有正确的地址。,2.EXTRN伪指令 EXTRN伪指令的功能是告诉汇编程序目前正在本段或本模块中所引用到的变量或标号,其实是定义在另一个段或模块中的。其一般格式为:EXTRN name:type,第14章模块化程序设计中对EXTRN有详细说明。,3.GROUP伪指令 一个程序可以有多个相同类型的内存段,例如:CODE,DATA,STACK。GROUP的功能是把它们集合在一个名称之下,构成一个段组,使它们能够放在64K的内存段内。其一般格式为:name GROUP seg_name,seg_name是段名,name为段组名,以下的GROU
11、P将SEG1和SEG2组织在同一个名为GROUPX的组内:,GROUPX GROUP SEG1,SEG2SEG1 SEGMENT PARA CODE ASSUME CS:GROUPX SEG1 ENDS;-SEG2 SEGMENT PARA CODE ASSUME CS:GROUPX SEG2 ENDS,4.INCLUDE伪指令 你可能会在不同的程序中用到一些内容相同的一组指令即宏指令。它们可以文件的形式保存,使任何程序都能使用它。假设有一个将ASCII数转换为二进制的程序存于C盘,名称是CONVERT.LIB。要获得此文件,可在源程序中加入INCLUDE句。例如:INCLUDE C:CONV
12、ERT.LIB,放置在原来应该编写这段ASCII数转换程序处。汇编程序会从磁盘找到此文件,并把它的指令语句载入(展开)使用者的程序。若汇编程序找不到此文件,会发出错误信息而不进行INCLUDE操作。汇编程序会在LST文本,把载入的指令语句每一行的第30个字,印上一个1(第33个字开始是源程序)。第14章讨论MACRO宏处理时有INCLUDE的实例。,5.LABEL伪指令 LABEL伪指令可以重新定义一个已定义名称的类型。其一般格式为:name LABEL type 通过LABEL我们可以使用如BYTE、WORD或DWORD等类型,来重新定义数据字段及结构(Structure)和记录(Recor
13、d)名称的类型,亦可用LABEL来重新定义调用指令的类型是NEAR或FAR。LABEL还可以把一个字段同时定义为DB和DW。下面说明BYTE及WORD这两种类型的使用。,REDEFBLABELBYTEFIELDWDW2532HREDEFWLABELWORDFIELDBDB25H DB32H.MOV AL,REDEFB;AL32H MOV BX,REDEFW;BX3225H,6.NAME伪指令 NAME伪指令提供另一种方法,为一个模块命名,写成:NAME name汇编程序按照下列顺序选出模块的名称:(1)有NAME伪指令时,则它的操作数name就是此模块的名称。(2)若没有NAME伪指令时,但有
14、TITLE,用其前六个字符作为模块名。本节PAGE与TITLE伪指令中对TITLE有详细说明。,(3)若没有NAME也没有TITLE,则源程序的名称就成为模块的名称。汇编程序会把所选用的名称交给链接程序。,7.ORG伪指令 汇编程序利用地址计数器计算常数或指令码在数据段或指令段内的相对地址(偏移地址)。假设汇编程序正在根据下列定义处理数据段:相对地址 名称 操作码 操作数 地址计数器 00 FLDA DW 2542H 02 02 FLDB DB 36H 03 03 FLDC DW 212EH 05 05 FLDD DD 00000705H 09,开始,地址计数器定为00。因为FLDA是两个字节
15、长,所以地址计数器就增加为02,以指出下一个数据项的地址。因为FLDB是一个字节长,所以地址计数器再增加为03,依次类推。你可以用ORG伪指令直接改变地址计数器的内容,再根据其内容以指出下一个数据项的地址,其一般格式为:ORG 表达式,表达式可以是一个绝对值,不可以是名称,而且必须形成一个两字节的绝对值。例如,下列数据项定义是在上述的FLDD之后进行的。相对地址 名称 操作码 操作数 地址计数器 ORG 0 00 00 FLDX DB?0101 FLDY DW?0203 FLDZ DB?04 ORG$+5 09,第一个ORG把地址计数器设置成00,其后的变量FLDX,FLDY和FLDZ就定义在
16、和FLDA、FLDB及FLDC相同的内存单元地址:相对地址:0 1 2 3 4 5 6 7 8 FLDA FLDB FLDC FLDD FLDX FLDY FLDZ,当操作数包含有$符号时,如上例的第二个ORG,它用来表示地址计数器的当前值,因此操作数$+5是把地址计数器设成04+5(即09)。使用FLDC会存取到相对地址为03处的一个字,而使用FLDZ则存取到相对地址为03处的一个字节:MOV AX,FLDC;一个字 MOV AL,FLDZ;一个字节,你可以用ORG的这个特性以重新定义内存单元的地址。但是,一定要确定ORG使地址计数器设定正确的值,才能算出所有重新定义内存单元的地址。而且,重
17、新定义的值会覆盖原来的常数。结构的定义STRUC内不能用ORG伪指令。,8.PAGE与TITLE 伪指令 PAGE与TITLE 伪指令是控制汇编输出显示格式的伪指令。PAGE与TITLE是每一个程序皆能使用的伪指令。1)PAGE 伪指令 PAGE处于程序的开头,你可以指定每一页所要列印的行数和每一行所要列印的最多字数。下面是设定每页60行和每行132个字符:PAGE 60,132,每页的行数范围是10255,而每行的字符数范围则为60132。若程序中没有PAGE说明时,汇编程序就假设为PAGE 66,80。假设行数设定为60,当汇编的程序已经列印了60行时,会自动跳到下一页并将页的计数值加1。
18、你若想在某一特定的行(例如段尾)强迫跳页,此时只要在需要跳页的行写上PAGE即可,后面不加参数。当遇到PAGE时,汇编程序列印时会自动跳页。,2)TITLE 伪指令 TITLE伪指令可以使得每页的顶端印出标题,如下所示:TITLE text text可以是列于磁盘目录的程序文件名。例如,假设程序的文件名为ASMSORT,下面写出了其名称并附上注释,长度最多为60个字符:TITLE ASMSORT-Assembler program to sort customer names,9.PROC 伪指令 以PROC伪指令开头而由ENDP结束的一段指令称为过程(Procedure)。最典型的用途是定义
19、指令段内的一个子程序。进入子程序(即过程)的方法是以CALL进入,并用RET返回。若一个子程序(子过程)与调用它的主程序(主过程)在同一内存段内,则子程序的类型为NEAR,用法如下:proc_name PROC NEAR,proc_name是过程名(主过程名或子过程名),若省略操作数NEAR,汇编程序会默认为NEAR。若一个子程序(子过程)位于调用程序(主过程)所在段的段外,在使用CALL调用时,被调用的子程序必须声明为PUBLIC。此外,被调用的程序放在不同的ASSUME CS之下,就该定为FAR的类型属性。例如:PUBLIC proc_name Proc_name PROC FAR 当以C
20、ALL调用一个子程序(子过程)时,在被调用程序的末尾必须使用RET返回,即在ENDP之前使用RET返回指令。第14章模块化程序设计中有使用例题。,10.PUBLIC 伪指令 PUBLIC伪指令的功能是通知汇编程序,目前汇编中的一些符号会被其他的模块所引用。其一般格式为:PUBLIC symbol,.第14章模块化程序设计中有关于PUBLIC的详细说明。,11.RECORD 伪指令 RECORD是定义记录伪指令,可以定义到位。所以,记录伪指令对数据的定义被限定在一个字或一个字节的范围内。这种数据模式应用在对工业过程的控制中。例如,若某一采集数据的量不足16位或不足8位,数据以半字节并行通讯。外部
21、设备调度只关心某一个字节中的某几个状态位经常用到。其一般格式为:Record_name RECORD 记录说明,.,记录说明,每一个“记录说明”的格式如下:Record_field_name:Length=Preassigment Record_field_name为记录字段名,Length为该字段名所占的长度,Preassigment为预赋值,可以任选。每一个字段名之后接一个冒号(:),长度以位的个数表示。长度的范围是116位。任意小于8位的长度视为8位,916位视为16位,必要时可向右靠齐,,例如定义一个记录:BITREC RECORD BIT1:3,BIT2:7,BIT3:6 就把一个字
22、分成了三个字段,各字段的名字分别为BIT1、BIT2和BIT3。BIT1定义BITREC的前三个位,BIT2定义其次的7个位,而BIT3定义最后的6个位,总共为16位,亦即一个字。若需要使用RECORD定义初值,,例如:BITREC RECORD BIT1:3=101B,BIT2:7=0110110B,BIT3:6=011010B 记录必须通过调用语句映像才能使用,即分配内存单元。例如:DEFBITS BITREC,不仅分配内存单元给这个记录,而且还把它与一个变量名DEFBITS联系在一起。这样分配内存会在数据段内产生Hex AD9A的机器码(存为9AAD)。尖括号内也可以重新定义BITREC
23、的数据项。图17-1的程序说明把BITREC定义成一个RECORD,但是这个记录的各字段不赋予初值。在这种情况下,数据段内用一个分配的声明可把各字段的初值定义在一对尖括号内。定义记录的运算符有WIDTH、Shift Count和MASK。用这些运算符可以改变记录的定义而不必修改其他用到此记录的指令。,1)WIDTH运算符 此运算符返回一个记录或记录内一个字段的长度,以位的个数表示。图17-1中A10之处是两个WIDTH的例子。第一条MOV指令返回BITREC整个记录的长度(16位);第二条MOV指令返回记录中BIT2字段的长度(7位)。在这两个例子中,汇编程序都产生立即操作数来表示长度。,-T
24、ITLE TRECORD(COM)Test of Record Pesudo-op0000 CODESG SEGMENT PARA codeASSUME CS:CODESG,DS:CODESG,SS:CODESG0100 ORG 100H0100EB02BEGIN:JMP SHORT MAIN;-,BITRECRECORDBIT1:3,BIT2:7,BIT3:6;Define record01029AADDEFBITS BITREC;Initzerecord;-0104MAINPROCNEAR0104A10:;Width:0104B710MOV BH,WIDTH BITREC;of recor
25、d(16)0106B007MOV AL,WIDTH BIT2;of field(07),0108 B10:;Shift Count:0108B10DMOV CL,BIT1;Hex 0D010AB106MOV CL,BIT2;06010CB100MOV CL,BIT3;00010EC10:;Mask:010EB8E000MOV AX,MASK BIT1;Hex E0000111BB1FC0MOV BX,MASK BIT2;1FC00114B9003FMOV CX,MASK BIT3;003F,0117D10:;Isolate BIT 2:0117A1 0102 RMOV AX,DEFBITS;g
26、et record011A251FC0AND AX,MASK BIT2;clear BIT 1&3011DB106MOV CL,BIT2;get shift 06011fD3E8SHR AX,CL;shift right0121E10:;Isolate BIT 1:,0121A10102 RMOV AX,DEFBITS;get record0124B10DMOV CL,BIT1;get shift 130126D3E6SHR AX,CL;shift right0128C3RET0129MAINENDP0129CODESEG ENDSENDBEGIN-,图17-1 RECORD伪指令的用法,2)
27、Shift Count 运算符 Shift Count用于获得位偏移量,是对于记录字段的直接存取,例如:MOV CL,BIT2 不是读取BIT2的内容,而是读取字段名最右面的位。汇编程序产生一个含有“偏移量”的立即数操作数,此立即数表示BIT2向右靠齐的位数。图17-1中,B10之处的三个例子返回BIT1、BIT2、BIT3的位偏移量,分别是0D、06和00。,3)MASK运算符 MASK运算符返回指定字段1的位屏蔽(Mask),具有定义该字段所占位置的功能。例如,在BITREC内定义的每一字段之MASK为:字段 二进制 十六进制 BIT3 0000000000111111 003F,在图17
28、-1中,C10处的三条指令返回BIT1、BIT2和BIT3的MASK值。在D10和E10处的指令分别说明如何从BITREC隔离出BIT2和BIT1。D10取得一个记录,把它存入AX寄存器,然后用BIT2的MASK进行AND操作:记录101 0110110 011010与BIT2作屏蔽000 1111111 000000 结果000 0110110 000000,其结果是把BIT2以外的各位清除。底下的两条指令把AX向右移6位,使BIT2向右靠齐:0000000000110110(Hex 0036)在E10内的范例,用于取得一个记录存入AX,因为BIT1是最左边的字段,所以此程序用它的偏移量向右
29、移13位:0000000000000101(Hex 0005),12.SEGMENT伪指令 任何汇编程序可以包含一个或多个段,利用SEGMENT伪指令就可以建立一个段及段名。在定义段的时候,应在段的末尾引入段结束伪指令ENDS。其一般格式为:seg_name SEGMENT AlignCombineClass.seg_name ENDS 所有参数都是可以任选的,它决定该段的联系形态。下面说明这些选项。,(1)Align:指出该段在内存的起始边界的物理地址,其选项有下列几种,X是十六进制数字:PAGE=XXX00(页边界)PARA=XXXX0(节边界)WORD=XXXXE(偶数边界)BYTE=X
30、XXXX(任意边界),(2)Combine:指出链接程序(Linker)处理此段的链接方式,称为段的组合类型。组合类型决定在程序中将该段与其他模块中的同名段如何组合起来。若没有指出组合类型,就不执行组合动作,表示该段是局部于此模块或程序的。组合类型有下列五种。PUBLIC:链接程序把该段以及在与其他模块链接期间,所碰到的具有相同名字的段链接起来,即最终这些段是连续的。,STACK:这种组合类型为堆栈的覆盖方式。被链接的程序必须至少定义一个STACK(堆栈段),若有一个以上的STACK,则堆栈指针设定成第一个堆栈段的首地址。链接程序一方面把本模块的同名段链接组合起来,把栈指针指向高地址,另一方面
31、别的模块中的同名段的内容却覆盖本模块的数据或信息,且覆盖是从高地址进行的。COMMON:规定COMMON会使该段与别的模块中的所有其他同名段共享相同的存储空间。最大的一个段决定此共同段的长度。,AT表达式:利用“AT表达式”,汇编程序把表达式的值当作段号,表示该段的绝对地址的数将成为(段号:0)。此方式使我们容易在固定的内存区域内把一些标志和变量定义在固定的偏移地址上,例如,ROM或低地址内存中的中断表。又例如,在ROM内的程序把图像显示缓冲区(Video Display Buffer)的地址定义为:VIDEO_RAM SEGMENT AT 0B800H,MEMORY:MEMORY 与COMM
32、ON类似,但经这样定义的段,会被定位在存储器中的所有段上面。(3)Class:该项是段的分类名,此项可用任何合法的名称,放在一对单引号内。分类名告诉链接程序把同名的段分在一块存储区域中。典型的例子是“STACK”和“CODE”。举例,链接程序可以把两个逻辑段结合成一个实际的段。,第一个SEG1SEGMENT PARA PUBLIC CODE汇编语言ASSUME CS:SEG1模块.SEG1ENDS-第二个SEG2SEGMENT PARA PUBLIC CODE汇编语言ASSUME CS:SEG2模块.SEG2ENDS-,多个段可以嵌套,只要内层的段完全套在外层之内即可。例如:SEG1SEGME
33、NT.SEG1开始 SEG2SEGMENT.SEG2的区域 SEG2 ENDS.SEG1继续 SEG1ENDS 若要把许多段组成模块群组(Groups),请参阅GROUP伪指令。,13.STRUC伪指令 STRUC伪指令能把一些相关的字段定义在一个“结构”(Structure)内。其一般格式为:Struc_name STRUC.形式参数(数据定义伪指令序列).Struc_name ENDS,结构以它的名称(结构名Struc_name)及STRUC伪指令开始,并以其结构名和ENDS伪指令结束。图17-2是结构的一个例子汇编程序把结构内定义的每个字节从第一个开始,一个接一个存储起来。合法的项目是D
34、B、DW、DD、DQ和DT的定义,并可选择性地加上字节名称。这里的形式参数用数据定义伪指令来定义。若其中的数据定义伪指令引入一个变量名,该变量名就表明某一字段的开始。为了避免混淆,将结构中引入的变量名称为字段名。,-TITLE DSTRUC(COM)Definition of a structure0000CODESGSEGMENTPARA codeASSUMECS:CODESG,DS:CODESG,SS:CODESG0100ORG100H0100 EB 29BEGIN:JMPSHORT MAIN;-PARLISTSTRUC;parameter list,0000 19MAXLENDB 250
35、001?ACTLENDB?0002 19 20 NAMEINDB 25 DUP()001BPARLISTENDS0102 19PARAMSPARLIST;Allocate structure0103?0104 19 20,011D5768617420 69PROMPTDB what is name?,$73206E61 6D 653F 24;-012BMAINPROCNEAR012B B4 09 MOVAH,09;Display prompt012D 8D 16 011D R LEADX,PROMPT0131 CD 21 INT21H,0133 B4 0AMOVAH,0AH;Accept in
36、put0135 8D 16 0102 RLEADX,PARAMS0139 CD 21INT21H013B A0 0103 RMOVAL,PARAMS.ACTLEN;Length of input,.013E C3 RET013F MAINENDP013F CODESGENDS ENDBEGIN-,图17-2 结构举例,应当注意,结构仅仅是一种数据结构的模式,结构伪指令本身并没有申请到存储空间和直接的赋值。因此,为了保存必要的存储空间,还必须依靠一个调用语句来把它映像到内存中。调用语句的格式为:Variable_name Struc_name 这里Struc_name是STRUC伪指令中的结构名,Variable_name是与结构的起始点联系在一起的变量名。,在图17-2中,STRUC以PARLIST的名称定义一串形式参数,用来从键盘输入名字。数据段内有一行语句把内存配置成该结构:PARAMS PARLIST 使它在程序内能够定址。本例的操作数中,尖括号内是空的。实际中你还可以用它去重新定义结构内的数据。,指令可以直接调用结构的名称。欲存取结构中的字段时,指令中要以结构的名称(此例中是PARAMS)来限定它们,其后接一个圆点,再接上字段名称,如下所示:MOV AL,PARAMS.ACTLEN 配置说明语句可用来重新定义结构内字段的内容。关于这项规则,请参阅汇编语言手册。,