汇编语言---常用伪指令

来源:互联网 发布:淘宝帆布鞋店 编辑:程序博客网 时间:2024/05/22 08:16

汇编语言---常用伪指令  

一、内存单元别名定义伪指令THIS

在程序中,如果需要以另外一种数据类型来访问同一存储单元时,可用强制类型转换操作符PTR来实现.但是,如果在程序中药经常以某种其它数据类型来访问同一存储单元的话,就必须在每次访问时都要加上强制类型转换操作符PTR;这样做虽然可行,但是,给编写程序带来了不必要的麻烦;
于是,汇编语言提供了另外一种操作符:THIS,它为同一存储单元取了另外一个别名,该别名可具有其自身的数据属性,但是段地址和偏移量是不变的;
THIS操作符的一般格式: 
THIS 数据类型

其中,数据类型就是常用的数据类型:BYTE、WORD、DWORD、NEAR、FAR,等等;
例如:
WBUFFER EQU THIS WORD  ;为下面一行的变量定义语句中定义的字节变量BUFFER取另外一个别名WBUFFER,类型是WORD类型;EQU为等价操作符;
BUFFER DB 20 DUP(0)    ;定义一个有20个DB型元素的数组变量;
经过这样的别名定义之后,就可以使用BUFFER来引用这个具有20个DB型元素的数组变量,通过变量BUFFER的别名WBUFFER也可以引用这个数组,但是,使用别名WBUFFER引用的是一个具有10个WORD(DW)型元素的数组;别名WBUFFER与变量名BUFFER具有完全相同的段地址和完全相同的段内偏移地址;它俩分别使用不同的数据类型来引用同一块内存区;
变量名BUFFER与它的别名WBUFFER的逻辑关系如图所示:
汇编语言---常用伪指令 - 哥哥 - 哥哥
这样,同一块内存区就具有两种不同的数据类型;于是,在指令中,引用不同的变量名,就具有不同的数据属性,但是段地址和段内偏移地址还是不变的:
A.如果引用变量别名WBUFFER,则是按照"字"属性来访问的;
B.如果引用变量名BUFFER,则是按照"字节"属性来访问的;
下面两条指令的效果是等价的:
MOV AX,WORD PTR BUFFER
MOV AX,WBUFFER
二、符号定义伪指令
符号定义伪指令有:等价伪指令EQU、等号伪指令=、符号名/标号名伪指令LABEL
1、等价伪指令EQU:
一般格式:
符号名 EQU 表达式

功能:使用EQU左边的"符号名"代表EQU右边的"表达式";
注意:等价定义语句不会给符号名分配存储空间,符号名不能与其它符号名同名,必须唯一,也不能被重新定义;
A.用符号名代表常量或表达式:当把一个常量或表达式定义成一个具有一定含义的符号名之后,在程序中就可以使用该符号名来代表该常量或表达式了;
例如:
NUMBER EQU 100         ;给缓冲区的长度取一个符号名
BUFF_LEN EQU NUMBER+2
CR EQU 13              ;给"回车"符的ASCII码定义一个符号名
LN EQU 10              ;给"换行"符的ASCII码定义一个符号名
BUFFER DB NUMBER,?,NUMBER DUP(?) ;用符号名来定义缓冲区;
B.用符号名代表字符串:用一个具有一定含义的符号名定义某一个较长的字符串,在随后的程序中就是用该符号名;
例如:
GREETING EQU 'How are you!'
在该定义之后,就可直接使用符号名GREETING带代表字符串"How are you!"了;
C.用符号名代表关键字或指令码
例如:
MOVE EQU MOV    ;给指令码MOV取另外一个别名MOVE
COUNTER EQU CX  ;给寄存器CX取一个叫做COUNTER的符号名
在该定义之后,就可以直接使用MOVE和COUNTER来分别代表MOV和CX了:
MOVE AX,CX      ;相当于指令MOV AX,CX
MOV COUNTER,BX  ;相当于指令MOV CX,BX
D.用符号名代表存储单元的别名:可对同一片存储区定义另一个数据类型的符号名;
例如:
WORD1 EQU THIS WORD       ;给后面的字节存储单元BYTE1取一个字属性的符号名
BYTE1 DB 12H,21H
FLAG DW 1234H
FLAG1 EQU BYTE PTR FLAG   ;给字变量FLAG的低字节取一个字节属性的符号名FLAG1
FLAG2 EQU BYTE PTR FLAG+1 ;给字变量FLAG的高字节取一个字节属性的符号名FLAG2
在该定义之后,就可以这样使用了:
MOV AX,WORD1  ;执行后,(AX)=2112H
MOV BL,FLAG1  ;执行后,(BL)=34H
MOV AL,FLAG2  ;执行后,(AL)=12H
E.使用符号名代表系统提供的一串符号:
例如:
BT EQU BYTE PTR ;给强制类型转换语句"BYTE PTR"取个符号名BT
WT EQU WORD PTR ;给强制类型转换语句"WORD PTR"取个符号名WT
有了这样的定义,就可以这样使用了:
SCORE DW 90     ;定义一个字类型变量
MOV AL,BT SCORE ;取字类型变量SCORE的低字节存放到AL中;
2.等号伪指令"="
汇编语言提供了使用等号"="伪指令来定义符号常数的方法,即:可用符号名代表一个常数;一般格式如下:
一般格式如下:
符号名 = 数值表达式

功能:用等号伪指令"="左边的"符号名"代表等号伪指令"="右边的"数值表达式";
注意:数值表达式在汇编时就应该可以计算出数值,它不能含有向前引用的符号名;使用等号伪指令"="定义的符号可以被重新定义,可被重新赋值;
例如:
ABC = 10 + 200*5    ;ABC的值是1010
ABC1 = 5*ABC + 21   ;ABC1的值是5071
COUNT = 1           ;COUNT的值是1
COUNT = 2*COUNT + 1 ;COUNT的值是3
等价伪指令EQU与等号伪指令"="的区别:
A.使用EQU伪指令定义的符号名不能与其它符号名重名,符号名必须唯一,且不能被重新定义;而使用等号伪指令"="定义的符号名可以重名,可以被重新定义,可被重新赋值;
B.使用EQU伪指令定义的符号名不仅可以代表某个常数或常数表达式,还可以代表字符串、关键字、指令码、一串符号(如:WORD PTR),等等;而使用等号伪指令"="定义的符号名仅仅用于代表数值表达式;
C.使用等价伪指令EQU定义的符号名和使用等号伪指令定义的符号名都不会被系统分配存储空间;
3.符号名定义伪指令LABEL
符号名定义伪指令LABEL与存储单元别名操作符THIS的功能类似,该伪指令定义一个指定的符号名,该符号名的段地址和段内偏移地址与下面紧跟着的一条变量定义语句中定义的变量的相应属性完全相同;但是该符号的类型是新指定的;LABEL伪指令的一般格式如下:
符号名 LABEL 数据类型
其中,数据类型就是常用的数据类型:BYTE、WORD、DWORD、结构类型、记录类型、NEAR、FAR,等等;
前面5种类型是变量的类型,后面2种类型是标号的类型;如果格式中的"数据类型"是前面5种类型之一,那么,符号名就是变量名;如果格式中的"数据类型"是后面2中类型之一,那么,符号名就是标号名;
例如:
WBUFFER LABEL WORD   ;WBUFFER与BUFFER具有相同的段地址和段内偏移地址,但是它们的数据类型不同;
BUFFER DB 200 DUP(?)
NEXT1 LABEL FAR      ;NEXT1与NEXT具有相同的段地址和段内偏移地址,但是,NEXT1是"远标号",NEXT是"近标号"
NEXT: MOV AX,BX
标号NEXT1和NEXT可用于不同的情况:当在同一个模块内部转移时,可使用近标号NEXT;当在不同的模块之间转移时,可使用远标号NEXT1;
三、偏移量调整伪指令
偏移量调整伪指令是在内存变量定义时用来调整内存变量起始偏移量的,它们在把源程序文件汇编成目标文件时起作用的;常用于偏移量调整的伪指令有:EVEN、ALIGN和ORG;它们的主要目的是:为了更有效地读取内存单元的内容;
1、偶对齐伪指令EVEN:
一般格式:  EVEN
该伪指令的作用是:告诉汇编程序(Assember),本伪指令下面的内存变量从下一个偶地址单元开始分配;
如果下一个存储单元的偏移地址恰好是个偶地址,那么该伪指令不起作用,否则,汇编程序将空出一个字节,从下一个偶地址单元处开始为其后的变量分配内存单元;
假设有如下变量定义,并且变量B1的偏移量是偶数,其内存单元分布,如下"图甲"所示:
B1 DB 12H  ;为了方便理解,不妨设B1的偏移量为XXXX0H
W1 DW 4567H
在上述定义情况下,在许多CPU系统中,当要读取字变量W1及其后面的字内容时,硬件设备将按照"图乙"所示的方式分两次读出该字内从容,然后再拼接成一个字的内容,这样,很明显,需要两个读内存周期,从而影响程序执行速度;
出现上述问题的原因主要是字变量W1在数据段内的偏移地址是奇数,为了保证其偏移量是偶数,需要在其定义之前加上伪指令EVEN:
B1 DB 12H
EVEN
W1 DW 4567H
这样定义之后,变量的内存分配机诶读取字变量W1的过程,如"图丙"所示:
这个时候,要读取字变量W1及其后面的字内存是,只需要一个读内存周期既可;
2、对齐伪指令ALIGN
一般格式:
ALIGN Num

其中,Num必须是2的幂次方,比如:1、2、4、8、16,等等;
该伪指令的作用是:告诉汇编程序,本伪指令下面的内存变量必须从下一个能够被Num整除的内存单元地址处开始分配内存;如果下一个内存单元的地址恰好能被Num整除,则该伪指令不起作用,否则,汇编程序将会空出若干字节,直到下一个内存单元地址能被Num整除为止;
下面的两组对齐效果是一致的:
第一组:
B1 DB 12H
EVEN
W1 DW 4567H
第二组:
B1 DB 12H
ALIGN 2
W1 DW 4567H
不难看出,伪指令ALIGN的功能要比EVEN更强大;
3.ORG伪指令
一般格式:
ORG 数值表达式

该伪指令的作用是:告诉汇编程序,本伪指令下面的内存变量从"数值表达式"所指定的偏移地址处开始分配内存;
假设有如下定义,且变量WORD1的偏移量为0:
WORD1 DW 1234H  ;offset = 0
BYTE1 DB 56H
WORD2 DW 0abcdH
ORG 1
BYTE2 DB ?
WORD3 DW ?
BYTE3 DB ?
其中,前三个内存变量的分配如"图丁"左边所示,但是,由于伪指令"ORG 1"的作用,说明其后面所定义的变量要从偏移地址为"1"的内存地址处开始分配内存;所以,后面三个变量的内存分布如"图丁"右边所示;
由此可见,这些变量的内存分配是相互重叠的,对某个变量的操作,很明显,会影响到与之重叠的变量;
另外,BYTE2、WORD3、BYTE3没有被赋初值,如果赋初值的话,则重叠部分的内存单元中原来的初值将会被覆盖掉;
以上就是三个伪指令EVEN、ALIGN和ORG的使用,其中,伪指令EVEN的使用频率较高;
下面是这三个偏移量调整伪指令下的内存变量在内存中的分布图:
汇编语言---常用伪指令 - 哥哥 - 哥哥
原创粉丝点击