汇编语言随笔

 汇编语言

第一章

定义:使用字母和符号来表示机器语言的命令,用十进制数或十六进制数来表示数据,这样的计算机程序设计语言就称为汇编语言

汇编语言与硬件密切联系

汇编语言中常用ASCII码表示字符,非打印的ASCII码共33个,打印的共99个

第二章

一般计算机包括五大部件:运算器、控制器、存储器、输入/输出设备,运算器和控制器合称CPU

总线分为:地址总线、数据总线、控制总线

单向总线:CPU-\>地址总线、地址总线-\>总存储器

指示存储单元编号的地址长度决定了存储器的最大容量,例如共10位,则大小为2\^10

指令是构成汇编语言程序的最基本单位

CPU执行指令序列就是重复执行:从存储器中取指令,执行指令规定的操作

执行步骤又分为:串行方式/指令流水方式

串行方式特点:当CPU在指令执行阶段,不需要占用系统总线,但此时总线不工作,所以总线的空闲时间较多;在从存储器取指令、取数据或存数据时,总线处于忙状态,其所占用的事件也比较长。而CPU只需花很短的时间去处理,所以大部分时间处于闲置状态

指令流水方式

执行单元EU:从指令队列中取出指令代码,有控制器译码后产生相应的控制信号,控制各部件完成指令规定的操作/对操作数执行各种指定的算数或逻辑运算、像总线接口单元发送数据

总线接口单元BIU:取指令、存储数据

CPU寄存器结构及其用途

![](media/1cfdeabd9c36dc36e3b94e87bf25ce9d.png)

第三章

指令=操作码+操作数

操作码:表示该指令应完成的具体操作

操作数:表示该指令的操作对象

提供操作数的方式:在指令代码中提供、在CPU通用寄存器或段寄存器中、在内存的存储单元中、在输入/输出接口的寄存器中

寻址方式

1.立即数寻址: MOV AH,20H可以为8或16位

它不需占用总线,立即数作为指令的一部分直接从BIU的指令队列中取出,不需占用总线周期

2.寄存器寻址: MOV AX,BX

存取寄存器操作数完全在CPU内部进行,u需要占用总线周期

一个存储单元逻辑地址表现方式:段基址,偏移量

3.存储器寻址

直接寻址

用符号表示:MOV BX,VAR-\>MOV
AL,DS:VAR,他表示将数据段中,偏移了VAR个字节距离的字单元内容送到寄存器BX中

用常数表示:MOV AX,DS:[64H](注意中括号)

间接寻址:操作数有效地址EA直接从基址寄存器或变址寄存器中获得

注:当指令中使用的是BP寄存器,则隐含表示SS段寄存器,其余情况则隐含使用DS段寄存器

基址寻址/变址寻址:操作码+寻址特征(BX/BP/SI/DI)+位移量

例:MOV AX,10H[SI]-\>MOV AX,DS:10H[SI]

注:当位移量为常数的时,不能加方括号

基址变址寻址:EA=基址(BX/BP)+变址(SI/DI)+位移量

例:MOV CX,100[BX][DI]

总结: 直接寻址:只有位移量

寄存器间接寻址:只有寄存器

基址/变址寻址:寄存器+位移量

基址变址寻址:寄存器2个+位移量

寻址过程都在EU中进行,算出物理地址后在BIU中取

4.串操作寻址方式:在寻找源操作数时,使用SI

在寻找目的串时,使用DI

操作结束后,SI DI会自动修改

5.I/O端口寻址

I/O端口编址方法(IN/OUT)

直接端口寻址:在指令中直接给出端口地址

例:IN AL,25H

寄存器间接端口寻址:把I/O端口的地址先送到DX 中,用DX作间接寻址寄存器

例:MOV DX,378H OUT DX,AL

注:端口号大于255必须使用间接寻址

指令系统

从指令的格式划分,一般可以分为三种:  
1.双操作数指令:OPR DEST SRC  
2.单操作数指令:OPR DEST  
3.无操作数指令  
对于无操作数指令,包含两种情况:  
(1)指令不需要操作数,如暂停指令HLT。  
(2)在指令格式中,没有显式地指明操作数,但是它隐含指明了操作数的存放地方,如指令PUSHF。

1、传送类指令

传送类指令的作用是将数据信息或地址信息传送到一个寄存器或存储单元中,可以分为以下四种情况:

1.通用数据传送指令

指令格式:MOV DEST, SRC  
作用:将源操作数指定的内容传送到目的操作数,即DEST\<=(SRC)。  
当指令执行完后,目的操作数原有的内容被源操作数内容覆盖,即目的操作数和源操作数具有相同内容。

MOV指令对标志寄存器的各位无影响;  
MOV指令可以是字节数据传送也可以是字数据传送,但是源操作数和目的操作数的长度必须一致。

MOV指令可以分为以下几种情况:

(1)立即数传送到通用寄存器或存储单元

例:

MOV AH, 10H

MOV AX, 2345H

MOV M-BYTE, 64H

MOV M-WORD, 2364H

注意:立即数只能作为源操作数,立即数不能传送给段寄存器。

(2)寄存器之间的传送

例:

MOV AH, CH

MOV DS, AX

MOV ES, BX

MOV AX, CS

MOV CS, AX ; 错误

注意:段寄存器CS只能作源操作数,不能作目的操作数。

(3)寄存器与存储单元之间传送

例:

MOV AL, [SI]

MOV [DI], AH

MOV AX, 10[BX]

MOV TABLE[BP], BX

MOV DS, [SI][BX]

综合,MOV指令在使用时需注意以下几个问题:  
立即数只能作为源操作数,且它不能传送给段寄存器。  
段寄存器CS只能作源操作数,段寄存器之间不能直接传送。  
存储单元之间不能直接传送数据  
MOV指令不影响标志位

2.交换指令

指令格式:XCHG DEST, SRC  
作用:源操作数和目的操作数两者内容相互交换,即:(DEST)\<=\>(SRC).  
指令对标志寄存器各位无影响;  
数据交换可以在寄存器之间或寄存器与存储单元之间进行。但是不能在存储单元之间进行数据交换。

寄存器只能使用通用寄存器。  
例:  
XCHG AX, BX  
XCHG AH, CH  
为了完成两个存储单元(DA_BYTE1和DA_BYTE2)之间的数据交换可以使用以下三条指令来实现。

MOV AL, DA_BYTE1 ; AL \<= (DA_BYTE1)  
XCHG AL, DA_BYTE2 ; (AL) \<=\> (DA_BYTE2)  
XCHG AL, DA_BYTE2 ; (AL) \<=\> (DA_BYTE2) 等价于 MOV DA_BYTE1, AL

3.标志传送指令

对标志寄存器进行存取的指令有4条,它们都是无操作数指令,即指令隐含指定标志寄存器、AH寄存器或堆栈寄存器为操作数。

(1)取标志寄存器指令

指令格式:LAHF  
作用:将标志寄存器的低8位送入AH寄存器,即将标志SF、ZF、AF、PF、和CF分别送入AH的第7、6、4、2、0位,而AH的第5、3、1位不确定。

指令执行对标志寄存器各位无影响,即标志寄存器各位不变。

(2)存储标志寄存器指令

指令格式:SAHF  
作用:将寄存器AH中的第7、6、4、2、0位分别送入标志寄存器SF、ZF、AF、PF和CF各标志位。而标志寄存器高8位中的各标志位不受影响。

(3)标志进栈指令

指令格式:PUSHF  
作用:先将堆栈指针SP减去2,使其指向堆栈顶部的空字单元,然后将16位标识寄存器的内容送SP指向的字单元。

(4)标志出栈指令

指令格式:POPF  
作用:将由SP指向的堆栈顶部的一个字单元的内容送入标志寄存器,然后SP的内容加2.

4.地址传送指令

这类指令有3条,它们的作用是将存储单元的地址送寄存器。

(1)装入有效地址

格式:LEA DEST, SRC  
其中:源操作数SRC必须是一个字节或字存储器操作数(地址),DEST必须是一个16位通用寄存器。

作用:将SRC存储单元地址中的偏移量,即有效地址EA传送到一个16位通用寄存器中。  
指令执行对标志寄存器各位无影响。  
例:  
LEA AX, [BX][SI]  
源操作数使用的是基址变址寻址方式,它所形成的有效地址就是BX的内容加上SI的内容。即

AX \<= (BX)+(SI)  
注意:它不是将BX和SI所寻址的存储单元的内容送入AX。  

比较指令LEA BX, DS:[23H]与MOV BX, DS:[23H]的功能

(2)装入地址指令指针

格式:LDS DEST, SRC  
LES DEST, SRC  
其中:DEST是任意一个16位通用寄存器。SRC必须是一个存储器操作数。  
作用:把SRC存储单元开始的4字节单元的内容(32位地址指针)送入DEST通用寄存器和段寄存器DS(LDS)或ES(LES指令),其中低字单元内容为偏移量送通用寄存器,高字单元内容为段基值送DS或ES。

例:LDS SI, TABLE[BX]  
设TABLE的值为0A02H,(BX)=34H,(DS)=2030H

2、算术运算类指令

8086/8088指令系统中有加、减、乘、除指令,这些指令可以对字节数据或字数据进行运算。

参加运算的数可以是无符号数,也可以是带符号数。带符号数用补码表示。  
参加运算的数可以是二进制数,也可以是十进制数(以BCD码表示)。

1.加法指令

指令格式:ADD DEST, SRC  
功能:目的操作数和源操作数相加,其和存放到目的操作数中,而源操作数内容保持不变,即DEST
\<= (DEST)+(SRC)。  
根据相加的结果将影响到标志寄存器的CF、PF、AF、ZF、SF和OF。  
DEST只能是通用寄存器或存储器操作数。不能是立即数。  
SRC可以是通用寄存器、存储器或立即操作数  
DEST和SRC不能都为存储器操作数。  
ADD指令可以是字节操作数相加,也可以是字操作数相加。  
例:分析下列各指令功能

(1)ADD AX, CX

功能:将寄存器AX的内容与CX的内容相加,结果传送到AX中

(2)ADD AH, DATA_BYTE

功能:将由直接寻址方式所指示的存储单元的内容与AH内容相加,结果送回AH中。

(3)ADD CX, 10H

功能:将常数10H加入到CX中。为字操作数指令

(4)ADD AX, [BX][SI]

功能:将由基址变址寻址方式所指示的存储单元的内容加入到AX中。

2.带进位加法指令

指令格式:ADC DEST, SRC  
该指令的功能与ADD基本相同,所不同的是其结果还要加上进位标志位CF的值,即:  
DEST \<= (DEST)+(SRC)+CF  
根据相加的结果设置标志寄存器中的CF、PF、AF、ZF、SF和OF  
注意:参加运算的进位CF是本条指令执行之前的值。  
用ADC指令可以实现数据长度大于16位的两数相加

例:计算12349678H + 377425H

MOV AX, 1234H

MOV BX, 9678H

ADD BX, 7425H

ADC AX, 37H

指令执行后,结果的高16位在AX,低16位在BX中。

3.加1指令

指令格式:INC DEST  
该指令为单操作数指令,其功能是将目的操作数加1,并送回到目的操作数,即:  
DEST \<= (DEST)+1  
目的操作数可以是任意的8位、16位通用寄存器或存储器操作数。目的操作数被视为带符号二进制数。

根据指令执行结果设置PF、AF、ZF、SF和OF标志,但不影响CF。INC指令主要用于某些计数器的计数和修改地址指针。

例:  
INC CL  
INC SI  
INC COUNT

4.减法指令

指令格式:SUB DEST, SRC  
功能:目的操作数的内容减去源操作数的内容,结果送入目的操作数,源操作数中内容保持不变。即:

DEST \<= (DEST)-(SRC)  
操作结果将影响标志位CF、PF、AF、ZF、SF和OF。  
目的操作数DEST和源操作数SRC可以是8位或16位的通用寄存器、存储器操作数,但两者不能同时为存储器操作数。立即数只能作源操作数。

例:

SUB AX, BX

SUB AH, 10H

SUB DX, DA_WORD

SUB DA_BYTE, BL

注意:减法指令对借位标志的影响,若采用变减为加的运算方法,则产生的进位与CF标志结果相反。

5.带借位减法

指令格式:SBB DEST, SRC  
该指令的功能与SUB指令基本相同,不同的是在两个操作数相减后再减去进位标志CF的值。即:

DEST \<= (DEST)-(SRC)-CF.  
注意:该CF的值是本条指令执行前的结果。  
SBB指令在使用上与ADC类似,主要用于长度大于16位的数相减,即将低16位相减的结果引入高位部分的减法中。

根据指令执行结果设置PF、AF、ZF、SF、OF和CF。

6.减1指令

指令格式:DEC DEST  
该指令为单操作数指令,将目的操作数的内容减1后,送回到目的操作数。即:DEST\<=(DEST)-1

DEST可以是8位16位的通用寄存器存储器操作数,该指令将DEST看作是带符号二进制数。  
根据指令操作结果PF、AF、ZF、SF和OF,但不影响CF。  
DEC指令的使用类似INC指令。主要用于计数和修改地址指针,计数方向与INC指令相反。  
例:  
MOV AL, 10H  
DEC AL  
JNC LOP

7.求负数指令

指令格式:NEG DEST  
功能:用零减去目的操作数的内容,并送回目的操作数,即:DEST\<=0-(DEST)  
DEST可以是任意一个8位或16位的通用寄存器或存储器操作数,被视为带符号的操作数。  
由于机器中带符号数用补码表示,求操作数的负数就是求补操作。因此,NEG指令也叫取补指令。

NEG指令将影响标志PF、AF、ZF、SF、CF和OF。  
对进位标志CF的影响:  
只有当操作数为零时,进位标志CF被置零,其它情况都被置1.  
对溢出标志OF的影响:  
当字节操作数为-128,或字操作数为-32768时,执行NEG指令结果操作数将无变化,但溢出标志OF被置1.

例:设AL中存放一个正数(AL)=25H,BL中存放一个负数(BL)=-58H,求它们的相反数,即负数。

NEG AL

NEG BL

指令执行后,(AL)=-25H=11011011B

(BL)=58H=01011000B

3、位操作类指令

1.逻辑运算指令

逻辑运算指令共有4条,它们的指令格式分别是:

与: AND DEST, SRC

或: OR DEST, SRC

异或: XOR DEST, SRC

非: NOT DEST

DEST和SRC可以是8位或16位的通用寄存器或存储器操作数,但两者不能同时为存储器操作数,SRC可以为立即数。

逻辑指令对标志位的影响:  
NOT指令对标志位无影响。而其余三条指令将根据结果影响SF、ZF和PF,而CF和OF总是置0,AF为不确定。

逻辑运算指令除用来实现各种逻辑运算之外,还常用于对字节或字数据的某些位的组合、分离或位设置。

指令系统

1.双操作数指令编码格式

(1)应用情形:一个操作数在寄存器中,零一个操作数在寄存器或存储器中

目的操作数在寄存器中,源操作数是立即数

(2)操作特征部分:

1)OPCODE:操作码字段:6bit,表示了该指令所执行的功能和两个操作数的来源

2)方向字段d:当源操作数位立即数是,d字段无效

3)字/字节字段:1字,0字节

(3)寻址特征部分:REG字段确定一个操作数,MOD和R/M字段确定另一个操作数

当d=1时,则目的字段由REG字段确定,而源操作数由MOD和R/M字段决定;d=0时相反

1)REG字段确定的一个操作数是某一通用寄存器的内容,即使用的是寄存器寻址方式

2)MOD和R/M字段决定一个操作数,既可以在寄存器里,又可以在存储器里

汇编语言数据

1、变量类型

字节量数据:用BYTE定义的8位字节量数据。(对应c语言中的char类型数据)

字量数据:用WORD定义的16位字量(对应c语言中的short类型数据)

双字量数据:用DWORD定义的32位双子量数据(对应c语言中的long类型数据)占用连续4个存储空间

2、变量定位

变量定义的存储空间是按照书写的先后顺序一个接着一个分配的,但是可以通过伪指令控制其存放的偏移地址。

(1) ORG指令

ORG伪指令将参数表达的偏移地址作为当前的偏移地址,格式为:ORG 参数

(2) ALIGN指令

多字节数据的存放不仅涉及到大端存放和小端存放,还涉及到边界是否对其的问题。为了获得更好的性能,常要进行地址边界对齐。格式ALIGN
N 其中N是对其边界的值。

3、变量属性

变量已经定义便具有两个属性:地址属性和类型属性

地址属性指的是首个变量所在的存储单元的逻辑地址

类型属性就是变量定义的数据单位,有字节量、字量、双字量、3字量、4字量和10字节量。依次使用类型名BYTE
WORD DWORD QWORD TBYTE表示。

地址操作符:主要用于获取变量名的地址,主要有SEG和OFFSET,分别获取变量名的段地址和偏移地址。操作符\$代表当前的偏移地址值,即前一个存储单元分配后当前可分配的存储单元的偏移地址。

变量名具有逻辑地址数据段中直接使用变量名代表他的偏移地址

类型操作符:主要使用变量名的类型属性,类型操作符PTR用于更改变量名的类型以满足对操作数类型的要求。还可以用lengthof操作符获取某变量名只想多少个数据项,用sizeof操作符获取变量占用多少字节的空间,也就是SIZEOF值=TYPE值Xlengthof值.对于字节变量和ASCII字符变量,lengthof和sizeof的结果相同。

4、数据存放方式

小端方式:高字节数据保存在高地址存储单元、低字节数据存放在低地址存储单元

大端方式:高字节数据存放在地地址存储单元、低字节数据存放在高地址存储单元

![](media/d6005850775696281531cfb6590e8f0e.png)

## 一、算术运算符

表 2
列出了算术运算符。表中所列出的前两个运算符,是属于单项运算符,仅表示数的正负。+、-、\*、/
运算是最常用的运算符,参加运算的数和运算的结果均是整数。除法运算的结果只取商的整数部分。而
MOD 运算符是进行整数除法,运算结果只取它的余数部分。

例如:

![在这里插入图片描述](media/13f874cbe2171ac27b183663c70d40ce.png)

表 2 算术运算符

上面的例子中 CONT 是两个变量的偏移量相减,其结果正是以 DATA1 为首地址占用的 6
个字节单元数。而 DATA3 是 DATA2 偏移量加 2,形成一个新的偏移量
38H,正好指向存放字符串“EF”的首址。

表 2 中后面两个运算符是进行逻辑移位。SHR 进行右移时,最左边以 0 填之;SHL
进行左移时,最右边以 0 填之。移位的位数由运算符 SHR/SHL
右边的次数确定。如次数大于等于
16,则结果恒为零。移位运算符与移位指令是完全不相同的两回事。移位运算符是对某一个具体的数(常数)在汇编时完成移位的,而移位指令是对一个寄存器或存储单元内容,在程序运行时执行移位的。根据它们在一条语句中出现的位置可以判断出它是移位运算符还是移位指令。例如:

![在这里插入图片描述](media/857d9ad8e8b3a4a4643c49adbae5b5e5.png)

上述 3 条指令与下面3条指令一一对应等效:

![在这里插入图片描述](media/4c062b71d3f9420c221b7792951c3625.png)

表 2 最后一个是下标运算符,它对存取数组元素是很有用的。[ ]
表示加法,把[表达式](https://so.csdn.net/so/search?q=%E8%A1%A8%E8%BE%BE%E5%BC%8F&spm=1001.2101.3001.7020)
1 和表达式 2 相加后形成一个存储器操作数地址。如下面两语句是等价的:

![在这里插入图片描述](media/0d86bba4faa6e96b8c748b47ab67fd7c.png)

即源操作数是一个存储器操作数,其地址是 DA 的偏移地址加 20H。再例如下面 5
个语句是相互等价的:

![在这里插入图片描述](media/2513a405222c8813441839012896b1c7.png)

但是两个存储器操作数(如两个变量名)不能相加。下面几个语句都是错误的:

![在这里插入图片描述](media/0790cb37427c3a93acc21dde0804ec38.png)

## 二、[逻辑运算符](https://so.csdn.net/so/search?q=%E9%80%BB%E8%BE%91%E8%BF%90%E7%AE%97%E7%AC%A6&spm=1001.2101.3001.7020)

表 3
列出了逻辑运算符,参加运算的数和运算的结果均是整数,逻辑运算是按位进行的。与移位运算符一样,逻辑运算符与逻辑运算指令是完全不同的两回事。例如:

![在这里插入图片描述](media/f70550e5f3c67d8a9c09e9dfd4308078.png)

上述指令与下面指令一一对应等效:

![在这里插入图片描述](media/9e5ff63fe598b9a4df2946f4f749de42.png)

表 3 逻辑运算符

## 三、[关系运算符](https://so.csdn.net/so/search?q=%E5%85%B3%E7%B3%BB%E8%BF%90%E7%AE%97%E7%AC%A6&spm=1001.2101.3001.7020)

表 4
列出了关系运算符。这些运算符是用于比较两个表达式的,表达式一定是常数或同段内的变量。若是常数,按无符号数比较。若是变量,则比较它们的偏移量。比较结果以真(全
1)、假(全 0)的形式给出。例如:

![在这里插入图片描述](media/16a44e081cc012d134bb7e16598316bd.png)

与下面两条指令完全一一对应等效:

![在这里插入图片描述](media/96766451efc0cd701056784d2777b27b.png)

设某数据段有:

![在这里插入图片描述](media/41037d4ce1c9de0462da701f2b23bf68.png)

在程序汇编时,若 NUM\<0ABH,则变量 VAR 的内容为 0FFFFH,否则它的内容为 0。

表 4 关系运算符

## 四、属性值返回运算符

这种运算符共有 5 个,如表 5
所示。它们加在变量名或标号前,通过运算后得到(返回)一个属性值。

表 5 属性值返回运算符

1.  SEG 运算符

SEG 为段值返回运算符。当 SEG
加在一个变量名或标号的前面时,得到的运算结果是这个变量或标号所在段的段基值。例如:

![在这里插入图片描述](media/65057cb3d14891fdef31a2ea5d70954f.png)

如果变量 X1 所在段的段基值为 0915H,变量 ARRAY 所在段的段基值为
0947H,那么上面两条指令汇编后分别为:

![在这里插入图片描述](media/341786d5eb8ecbeee345b4e367e6f846.png)

由于任意一个段的段基值是 16 位二进制数,所以 SEG 运算符返回的数值也是 16
位二进制数。

1.  OFFSET 运算符

OFFSET
为偏移值返回运算符。当该运算符加在一个变量名或标号前面时,将得到这个变量或标号在它段内的偏移量。例如:

![在这里插入图片描述](media/06e874be0ee21660e6798bb58686cf36.png)

设 KZ 在它段内的偏移量是 15H,那么这个指令汇编后就是:

![在这里插入图片描述](media/37969dd8032c9b417cc450bdb76151fb.png)

这个运算符十分有用。例如,现有以 ARRAY
为首址的字节数组,为了逐个字节进行某种操作。可以使用下面的程序段:

![在这里插入图片描述](media/3ecd5b071e98a7c444a74c8d0f184341.png)

在这段程序中,首先把数组变量的首字节偏移量送给 SI,把寄存器 SI
作为数组的地址指针。这样,在数组的逐个字节处理(即在 LOP
循环)中,使用寄存器间接寻址方式,每处理完一个字节,很方便地对地址指针 SI
进行修改,使它指向下一个字节。

当用 DW 或 DD
伪指令设置了某变量的地址指针后,这时程序设计人员为了获得变量的偏移量,既可以用
OFFSET 运算符,也可以直接取出地址指针。请分析下面的语句中 4 条 MOV
指令各自的含义和指令执行的结果。

![在这里插入图片描述](media/c086c34dbf402886650318f87b4909d5.png)

1.  TYPE 运算符

TYPE
为类型属性值返回运算符,是取变量或标号的类型属性值(变量和标号的类型属性值如前所述)。其中变量的类型值正好表示它们每个数据所占有的存储单元字节数。而标号的类型值没有什么物理意义。例如:

![在这里插入图片描述](media/b346167e3f11b3099744a2778dc45b63.png)

上述 3 条指令汇编后分别为:

![在这里插入图片描述](media/7d8cbfabc860f65c1f688795c055b661.png)

1.  LENGTH 运算符

LENGTH
为变量的元素总和运算符。仅加在变量的前面,返回值表示数组变量的元素个数。如果变量是用重复数据操作符
DUP 说明的,则返回外层 DUP 给定的值;如果没有 DUP 说明,则返回的值总是 1。例如:

![在这里插入图片描述](media/7de28731aa9150c7ec9030342a1eaf47.png)

1.  SIZE 运算符

SIZE
为变量字节总和运算符。这个运算符仅加在变量的前面,表示数组变量所占的总字节数。返回值等于
LENGTH 和 TYPE 两个运算符返回值的乘积。例如,对于前面例子中 K1,K2,K3,K4
变量,下面指令就表示出 SIZE 运算符的返回值:

![在这里插入图片描述](media/80e517b9d41189ebcb6c88fd7879d2e7.png)

3 个运算符 TYPE,LENGTH,SIZE
对处理数组类型变量是很有用的。例如,为了实现某数组各元素的累加,而且从最后一个元素开始累加。可以编制如下程序段:

![在这里插入图片描述](media/a172fddd7167793da48f6b4b30c0ff73.png)

在上述程序中,地址指针 SI 的设置是用 SIZE 和 TYPE
运算符计算确定的,使它指向数组的最后一个元素。CX
存放数组元素个数,供循环计数用。

注意:

LENGTH 和 SIZE 运算符仅加在变量前面,且这个变量必须是用 DUP
形式定义的;否则,它们仅返回一项数据的情况。

## 五、属性修改运算符

这种运算符是对变量、标号(过程名)、直接或寄存器间接寻址的存储器操作数的类型进行修改、指定。

### (一)PTR 运算符

PTR 是类型属性修改运算符。

格式:类型 PTR 操作数

功能:将操作数强制修改为 PTR 左边给出的类型。这种修改是临时性的,仅在有 PTR
运算符的语句内有效。

说明:操作数是指要修改类型属性的标号、过程名、变量、直接或寄存器间接寻址的存储器操作数。类型可以是
BYTE、WORD、DWORD(操作数是变量、直接或寄存器间接寻址的存储器操作数时)或
NEAR、FAR 等(操作数是标号、过程名时)。

有两种情况需要使用 PTR 运算符。

(1)由于编程需要,临时修改变量的类型属性。

例如:

![在这里插入图片描述](media/7a7730158a01202f6968ef03aa826533.png)

(2)当指令语句中的操作数类型不明确时,用以明确操作类型。

例如,语句“INC [BX]”是错误的,因为在对该指令语句进行汇编时,不能确定 [BX]
指的是字节单元还是字单元。

再如,“SUB
[SI],30H”这条语句也不能让汇编程序确定是进行字节减法还是字减法运算,因为常数
30H 是没有类型的,可以看成是八位数 30H,也可以看成是十六位数 0030H。

因此,这两条语句必须用 PTR
运算符对类型加以明确,否则在汇编源程序时将会产生语法错误。上述两条语句可修改如下:

![在这里插入图片描述](media/1c8c0c9e3bf6e4c8932aebe158bdb1c8.png)

从上述例子可以看出,常数、直接或寄存器间接寻址的存储器操作数类型都是不明确的。在一条指令语句中如果只有一个操作数,其类型必须明确;如果有两个操作数,只要有一个类型是明确的就可以,否则,必须使用
PTR 运算符明确类型。

### (二)HIGH/LOW 运算符

这两个运算符叫字节分离运算符,用于分离运算对象的高字节和低字节部分。

格式:HIGH 表达式

LOW 表达式

表达式必须具有常量值,即一个常数或在汇编源程序时能确定的段/偏移量值的地址表达式,HIGH/LOW
运算符用于分离出段/偏移量的高字节或低字节。例如:

![在这里插入图片描述](media/099032320a9d5740785d42446f2f952f.png)

设 DATA 段的段基值是 0926H,那么上述几条指令汇编后分别为:

![在这里插入图片描述](media/98c81dc96ed6f690841d43219dfecb1d.png)

但是 HIGH/LOW
运算符不能用来分离某一个寄存器或存储器操作数内容的高字节/低字节。例如,下面的几条指令语句是错误的:

![在这里插入图片描述](media/8d55e0a882cfc52fd57f17d9ad724f12.png)

## 六、运算符的[优先级](https://so.csdn.net/so/search?q=%E4%BC%98%E5%85%88%E7%BA%A7&spm=1001.2101.3001.7020)

当一个表达式中同时有几个运算符时,按运算符优先级顺序执行。运算符的优先级别如表 6
所示。其中,WIDTH、MASK
是记录中用的运算符。汇编源程序时按照以下规则计算表达式的值。

(1)先执行优先级别高的运算。

(2)优先级别相同的操作,从左至右顺序进行。

(3)可以用圆括号改变运算的顺序。

例如下面两个表达式:

![在这里插入图片描述](media/c34198bd6c4531a3232f706083cbfc0c.png)

它们的值分别是:

![在这里插入图片描述](media/55e0f47617db2be9b9ceda2dea854890.png)

表 6 运算符的优先级

posted @   BYTT  阅读(326)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示