《汇编语言(王爽)》

汇编语言发展至今,由以下三类指令组成:汇编指令、伪指令、其他符号。

8086CPU有20位地址总线,可以传送20位地址,达到1MB的寻址能力。

物理地址=段地址×16+偏移地址

8086CPU有14个寄存器:
AX,BX,CX,DX;CS,DS,SS,ES;IP,SI,DI,BP,SP;PSW
CS(IP) DS,ES(BX,SI,DI,BP) SS(SP,BP)

DEBUG功能

r命令查看、改变CPU寄存器中的内容
d命令产看内存中的内容
e命令改写内存中的内容
u命令将内存中的机器指令翻译成汇编指令
t命令执行一条机器指令
a命令以汇编指令的格式在内存中写入一条机器指令
p命令跳过循环和执行中断
g命令,“g 0016”直接跳到cs:0016

在内存和寄存器之间传送字型数据时,高地址单元和高8位寄存器,低地址单元和低8位寄存器相对应。栈也是。

汇编的一个经典栗子,看完再继续向下学习详细指令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
assume cs:code,ds:data
data segment
db 'welcome to masm!'
data ends
code segment
start: mov ax,data
mov ds,ax
mov bx,0 ;ds:bx指向data字符串
mov ax,0b800h
mov es,ax
mov si,0 ;es:si指向显存
mov cx,16
s: mov al,[bx] ;字符赋值al
mov ah,02h ;绿色
mov es:[si].720h,ax ;写入第12行64列
mov ah,14h ;绿底红色
mov es:[si].7c0h,ax ;写入第13行64列
mov ah,71h ;白底蓝色
mov es:[si].860h,ax ;写入第14行64列
inc bx ;指向下一字符
add si,2 ;指向下一显存单元
loop s
mov ax,4c00h
int 21h
code ends
end start


push指令执行步骤:1. SP=SP-2 ; 2.向SS:SP指向的字单元中送入数据
pop指令执行步骤:1. 从SS:SP指向的字单元读取数据; 2.SP=SP+2
任意时刻,SS:SP指向栈顶元素。


mov指令
mov ax,[0] 送入0
mov ax,ds:[0] 送入内存中的值
mov ax,[bx] 送入内存中的值
mov ax,ds:[bx] 送入内存中的值


add 指令
add ax,[1]把1加到ax寄存器上


sub指令
sub ax,[1]把ax寄存器中的值减1


and 逻辑与指令,按位进行与运算
将AL的第六位设为0:and al,10111111B


or 逻辑或指令,按位进行或运算
将AL的第六位设为1:or al,01000000B
大写字母的ASCII码第五位为0,小写字母的第五位为1.


使用寄存器BP,如果没有显性地给出段地址,段地址就默认在SS中。
Mov ax,[bp]:(ax)=((ss)16+(bp))
Mov ax,[bp+si+idata]:(ax)=((ss)
16+(bp)+(si)+idata)


机器指令并不关心数据的值是多少,而关心指令执行前一刻,它将要处理的数据所在的位置。指令在执行前,所要处理的数据可以在三个地方:CPU内部,内存,端口
Mov bx,[0]内存,ds:0单元
Mov bx,axCPU内部,ax寄存器
Mov bx,1CPU内部,指令缓冲器


8086CPU的指令,可以处理两种尺寸的数据,byte和word。所以在机器指令中要指明,指令进行的是字操作还是字节操作。

  1. 通过寄存器名指明要处理的数据的尺寸;
  2. 没有寄存器名存在的情况下,用操作符byte ptr和word ptr指明内存单元的长度

DIV除法指令:

  1. 除数:
    有8位和16位两种,在一个寄存器或内存单元中
  2. 被除数:
    默认放在AX或AX和DX中
    如果除数为8位,被除数则为16位,默认在AX中存放;
    如果除服为16位,被除数则为32位,在DX和AX中存放,DX存放高16位,AX存放低16位。
    3.结果:
    如果除数为8 位,则AL存储除法操作的商,AH存储除法操作的余数;
    如果除数为16位,则AX存储除法操作的商,DX存储除法操作的余数。

dup操作符,与db,dw,dd等数据定义伪指令配合使用的,用来进行数据的重复。
db 3 dup ('abc', 'ABC')


offset取得标号偏移地址


转移指令:可以控制CPU执行内存中某处的代码的指令。
jmp short 标号
jmp 标号
jmp far ptr 标号

1.只修改IP时,称为段内转移,如:jmp ax
短转移:IP的修改范围-128——127 近转移:IP的修改范围-32768——32767

2.同时修改CS和IP 时,称为段间转移,如:jmp 1000:0


jcxz指令 有条件转移指令。
所有的有条件转移指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围都是:-128——127.

jcxz 标号
(如果(cx)=0,转移到标号处执行。)
操作:当(cx=0)时,(IP)=(IP)+8位位移:
8位位移=”标号”处的地址 - jcxz指令后第一个字节的地址
相当于:

1
if((cx)==0) jmp short 标号


loop指令 循环指令
所有的循环指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围都是:-128——127.

loop 标号
((cx)=(cx)-1,如果(cx)≠0,转移到标号处执行。)
操作:
1.(cx)=(cx)-1;

  1. 如果(cx)≠0,(IP)=(IP)+8位位移。如果(cx)=0,什么也不做(程序向下执行)
    相当于:
    1
    2
    (cx)--
    If((cx)0) jmp short 标号`

ret指令 用栈中的数据,修改IP的内容,从而实现近转移
CPU执行ret指令时,
1.(IP)=((SS)*16+(SP))

  1. (SP)=(SP)+2
    相当于:
    1
    POP IP

Retf 指令 用栈中的数据,修改CS和IP 的内容,实现远转移
CPU执行retf指令时,

  1. (IP)=((SS)*16+(SP))
  2. (SP)=(SP)+2
  3. (CS)=((SS)*16+(SP))
  4. (SP)=(SP)+2
    相当于:
    1
    2
    POP IP 
    POP CS

CALL 指令不能实现短转移,除此之外,和JMP指令原理相同。
CPU 执行CALL指令时,
1.将当前的IP或CS和IP压入栈中
2.转移

call 标号(将当前IP压栈后,转到标号处执行指令)
相当于:

1
2
PUSH IP
JMP near ptr 标号

call far ptr 标号 (段间转移)
相当于:

1
2
3
push cs
Push IP
Jmp far ptr 标号

call 16位寄存器
相当于:

1
2
PUSH IP
Jmp 16位寄存器

call word ptr 内存单元地址
相当于:

1
2
push IP
Jmp word ptr 内存单元地址

call dword ptr 内存单元地址
相当于:

1
2
3
push CS
push IP
Jmp dword ptr 内存单元地址

call 和 ret配合使用实现子程序的机制
框架如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Assume cs:code
Code segment
Main: :
:
Call sub1
:
Sub1: :
Call sub2
:
Ret
Sub2:
:
Ret
Code ends
End main


mul 乘法指令;
(1)两个相乘的数,要么都是8位,要么都是16位;如果是8位,一个默认放在AH中,另一个放在8位寄存器或内存字节单元中;如果是16位,一个默认在AX中,另一个放在16位寄存器或内存字单元中。
(2)8位乘法,结果默认放在AX中;16位乘法,结果高位默认在DX中存放,低位在AX中存放。


标志寄存器flag作用:
(1)用来存储相关指令的某些执行结果
(2)用来为CPU执行相关指令提供行为依据
(3)用来控制CPU的相关工作方式

第6位ZF,零标志位。它记录相关指令执行后,其结果是否为0。如果结果为0,那么ZF=1,不为0,那么ZF=0.影响标志寄存器的指令,如:add,sub,div,inc,mul,or,and等,他们大都是运算指令;有的指令对标志寄存器没有影响,比如:mov,push,pop等,他们大都是传送指令。

第2位PF,奇偶标志位。它记录相关指令执行后,其结果的所有二进制中1的个数是否为偶数。如果1的个数为偶数,PF=1,如果为奇数,那么PF=0.

第7位SF,符号标志位。它记录相关指令执行后,其结果(实际结果(寄存器中存放的结果)并非逻辑结果)是否为负。如果结果为负,SF=1,如果非负,SF=0。CPU在执行ADD等指令的时候,包含了两种含义。将得到用同一种信息记录的两种结果,关键在于我们的程序需要哪一种结果。SF标志就是CPU对有符号数运算结果的一种记录,它记录数据的正负。在我们将数据当作有符号数来运算的时候,可以通过它来得知结果的正负。如果我们将数据当作无符号数来运算,SF的值则没有意义,虽然相关的指令影响了它的值。

第0位CF,进位标志位。一般情况下,在进行无符号数运算的时候,它记录了运算结果的最高位向更高位的进位值,或从更高位的借位值。

第11位OF,溢出标志位。一般情况下,OF记录了有符号数运算的结果是否发生了溢出。如果发生溢出,OF=1,如果没有,OF=0。CF 是对无符号数运算有意义的标志位,而OF是对有符号数运算有意义的标志位。

adc带进位加法指令,它利用了CF位上记录的进位值。
指令格式:adc 操作对象1,操作对象2
功能:操作对象1=操作对象1+操作对象2+CF
加法:1低位相加;2高位相加再加上低位相加产生的进位值
下面指令和add ax,bx具有相同的结果
Add al,al
Adc ah,ah

sbb 带借位减法指令,它利用了CF位上记录的借位值。
格式:sbb 操作对象1,操作对象2
功能:操作对象1=程序对象1-程序对象2-CF
Sbb ax,bx实现的功能:(ax)=(ax)-(bx)-CF

cmp 比较指令,cmp的功能相当于减法指令,只是不保存结果。Cmp指令执行后,将对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。
格式:cmp 操作对象1,操作对象2
功能:计算操作对象1-操作对象2 但并不保存结果,仅仅根据计算结果对标志寄存器进行设置。
cmp ax,bx ;无符号数的比较
如果(ax)=(bx)则(ax)-(bx)=0,所以:ZF=1;
如果(ax)≠(bx)则(ax)-(bx)≠0,所以:ZF=0;
如果(ax)<(bx)则(ax)-(bx)将产生借位,所以:CF=1;
如果(ax)≥(bx)则(ax)-(bx)不必借位,所以:CF=0;
如果(ax)>(bx)则(ax)-(bx)既不借位,结果又不为0,所以:CF=0并且ZF=0
如果(ax)≤(bx)则(ax)-(bx)既可能借位,结果可能为0,所以:CF=1或ZF=1。
有符号数的比较:SF只能记录实际结果的正负,发生溢出的时候,实际结果的正负不能说明逻辑上真正结果的正负。但是逻辑上的结果的正负,才是cmp指令所求的真正结果,所以我们在考察SF的同时考察OF,就可以得知逻辑上真正结果的正负,同时就知道比较的结果。
1.如果SF=1,而OF=0
没有溢出,逻辑结果的正负=实际结果的正负
SF=1,实际结果为负,(ax)<(bx)
2.如果SF=1, 而 OF=1
OF=1,说明有溢出,逻辑上真正结果的正负≠实际正负
SF=1,实际结果为负,如果因为溢出导致了实际结果为负,则逻辑上真正的结果必然为正。
这样SF=1, OF=1,说明了(ax)>(bx)。
3.如果SF=0,而 OF=1 说明:(ax)<(bx)
OF=1,说明有溢出,逻辑结果的正负≠实际结果的正负
SF=0,实际结果非负,有溢出结果非0,所以实际结果为正,如果因为溢出导致了实际结果为正,则逻辑上真正的结果必然为负。
4.如果SF=0,而 OF=0
没有溢出,且结果非负,所以(ax)≥(bx)

检测比较结果的条件转移指令
“转移”指的是它能够修改IP,而“条件”指的是它可以根据某种条件,决定是否修改IP。这些条件转移指令通常都和CMP相配合使用,就好像call和ret指令通常相配合使用一样。
常用的根据无符号数的比较结果进行转移的条件转移指令有:
指令 含义 检测位
Je 等于则转移 ZF=1
Jne 不等于则转移 ZF=0
Jb 低于则转移 CF=1
Jnb 不低于则转移 CF=0
Ja 高于则转移 CF=0且ZF=0
Jna 不高于则转移 CF=1或ZF=1
E :equal b: below a: above n: not j: jump

flag 的第10位是DF,方向标志位。在串处理指令中,控制每次操作后si,di 的增减。
DF=0 每次操作后si,di 递增
DF=1 每次操作后si,di 递减
Movsb 描述:mov es:[di],byte ptr ds:[si];(8086不支持这样的格式。)
如果DF=0; inc si inc di
如果DF=1; dec si dec di
功能:将ds:si指向的内存单元的字节送入es:di中,然后根据标志寄存器DF位的值,将si和di递增或递减。
Movsw 将ds:si指向的内存单元的字送入es:di中,然后根据标志寄存器DF位的值,将si和di递增2或递减2。

一般,movsb 和movsw都和rep配合使用,
格式:rep movsb
汇编描述:s: movsb
Loop s
可见,rep的作用是根据cx的值,重复执行后面的串传送指令。
8086对DF的设置:cld置0, std置1

pushf 将标志寄存器的值压栈,popf从栈中弹出数据,送入标志寄存器中。

四种内中断: 除法错误、单步执行、执行int0指令、执行int指令

中断信息中包含中断类型码,中断类型码为一个字节型数据,可以表示256种中断信息的来源,即中断源。

中断向量表,中断处理程序的入口地址列表。
中断向量表在内存中保存,其中存放着256个中断源所对应的中断处理程序的入口。
中断向量表指定存放在内存地址0处,从0000:0000到0000:03E8的1000个段媛中存放着中断向量表。
一个表项存放着一个中断向量,也就是一个中断处理程序的入口地址,对于8086CPU,这个入口地址包括段地址和偏移地址,所以一个表项占两个字,高地址字存放段地址,低地址字存放偏移地址。

8086CPU在收到中断信息后,引发的中断过程为:
1.(从中断信息中)取得中断类型码; N

  1. 标志寄存器的值入栈; pushf
  2. 设置标志寄存器的第八位TF和第九位IF的值为0; TF=0,IF=0
  3. CS的内容入栈 ; push CS
  4. IP的内容入栈; push IP
  5. 从内存地址为:中断类型码4和中断类型码4+2的两个字单元中读取中断处理程序的入口地址设置IP和CS。(IP)=(N4),(CS)=(N4+2)
    在最后一步完成后,CPU开始执行程序员编写的中断处理程序。

CPU随时都可能执行中断处理程序,所以中断处理程序必须一直存储在内存某段空间之中。

中断处理程序的编写步骤:
1.保存用到的寄存器
2.处理中断
3.恢复用到的寄存器
4.用iret指令返回

Iret指令的功能用汇编语法描述为:
Pop IP
Pop CS
Popf
Iret指令执行后,CPU回到执行中断处理程序前的执行点继续执行程序。

CPU在执行完一条指令之后,如果检测到标志寄存器的TF位为1,则产生单步中断,引发中断过程。单步中断的中断类型码为1,则它引发的中断过程为:
[1]取得中断类型码1;
[2]标志寄存器入栈,TF,IF设置为0;
[3]CS,IP入栈;
4=(14),(CS)=(14+2)。

Debug提供了单步中断的中断处理程序,功能为显示所有寄存器中的内容后等待输入命令。

响应中断的特殊情况:在执行完向SS寄存器传送数据的指令后,即便是发生中断,CPU也不会响应。因为,SS:SP联合指向栈顶,而对他们的设置应该连续完成,如果在执行完设置SS的指令后,CPU响应中断,引发中断过程,要在栈中压入标志寄存器、CS和IP的值,而SS改变,SP并未改变,SS:SP指向的不是正确的栈顶,将引起错误。所以CPU在执行完设置SS的指令后,不响应中断。这给连续设置SS和SP,指向正确的栈顶提供了一个时机。因此我们将设置SS和SP 的指令连续存放,使得设置SP的质量紧接着设置SS的指令执行,而在此之前,CPU不会引发中断过程。

  1. int 指令格式:int n n为中断类型码,它的功能是引发中断过程
    CPU执行INT N指令,相当于引发一个N号中断的中断过程:
    [1]取中断类型码n
    [2]标志寄存器入栈,IF=0,TF=0
    [3]CS、IP入栈
    [4](IP)=(N4),(CS)=(N4+2)
    从此处转去执行N号中断的中断处理程序。

  2. 在系统的ROM中存放着一套程序,称为BIOS(基本输入输出系统),BIOS中主要包括:
    [1]硬件系统的检测和初始化程序;
    [2]外部中断和内部中断的中断例程;
    [3]用于对硬件设备进行I/O操作的中断例程;
    [4]其他和硬件系统相关的中断例程。
    操作系统DOS也提供了中断例程,从操作系统的角度来看,DOS的中断例程就是操作系统向程序员提供的编程资源。
    程序员在编程的时候,可以用INT 指令直接调用BIOS和DOS提供的中断例程,来完成某些工作。

  3. BIOS和DOS中断例程的安装:
    [1] 开机后,CPU一加电,初始化(CS)=0FFFFH,(IP)=0,自动从FFFF:0单元开始执行程序,FFFF:0处有一条跳转指令,CPU执行该指令后,转去执行BIOS中的硬件系统检测和初始化程序。
    [2]初始化程序将建立BIOS所支持的中断向量,即将BIOS提供的中断例程的入口地址登记在中断向量表中。注意,对于BIOS所提供的中断例程,只需将入口地址登记在中断向量表中即可,因为他们是固化到ROM中的程序,一直在内存中存在。
    [3]硬件系统检测和初始化完成后,调用INT 19H进行操作系统的引导,从此将计算机交由操作系统控制。
    [4]DOS启动后,除完成其他工作外,还将它所提供的中断例程装入内存,并建立相应的中断向量。

1.在PC机系统中,和CPU通过总线相连的芯片除各种存储器外,还有:
[1]各种接口卡(如:网卡、显卡)上的接口芯片,他们控制接口卡进行工作
[2]主板上的借口芯片,CPU通过他们对部分外设进行访问
[3]其他芯片,用来存储相关的系统信息,或进行相关的输入输出处理
这些芯片中,都有一组可以由CPU读写的寄存器,他们在物理上可能处于不同的芯片中,但是他们在以下两点上相同:
[1]都和CPU的总线相连,当然是通过他们所在的芯片进行的
[2]CPU对他们进行读写的时候,都通过控制线向他们所在的芯片发出端口读写命令。
可见,从CPU的角度,将这些寄存器都当作端口,对他们进行统一的编址,从而建立了一个统一的端口地址空间。每一个端口在地址空间中都有一个地址。

2.端口地址和内存地址一样,通过地址总线来传送,在PC系统中,CPU最多可以定位64K个不同的端口。端口地址的范围:0~65535.
端口的读写::in和out指令
In al ,60h 从60H号端口读入一个字节
在in和out指令中,只能使用ax和al来存放从端口中读入的数据或要发送到端口中的数据。访问8位端口用ax,访问16位端口用ax。
对0~255以内的端口进行读写时:
In al , 20h
Out 20h , a
对256~65535的端口读写时,端口号放在dx中
Mov dx , 3f8h
In al , dx 从端口3F8读入一个字节
Out dx, al 向端口3F8写入一个字节

  1. CMOS RAM 芯片简称CMOS 芯片特征:
    [1]包含一个时钟和一个有128个存储单元的RAM存储器
    [2]靠电池供电,关机后内部时钟正常工作,RAM中信息不丢失
    [3]128个字节的RAM中,内部时钟占用0—0dh单元来保存时间信息,其余大部分单元用于保存系统配置信息,供系统启动时BIOS程序读取。BIOS也提供了相关的程序,使我们可以在开机的时候配置CMOS RAM中的系统信息。
    [4]该芯片内部有两个端口,端口地址为70H和71H。CPU通过这两个端口来读写CMOS RAM
    [5]70H为地址端口,存放要访问的CMOS RAM单元的地址;71H为数据端口,存放从选定的CMOS RAM单元中读取的数据,或要写入到其中的数据。可见,CPU对CMOS RAM的读写分两步进行,比如:读CMOS RAM的2号单元:
    ①将2送入端口70H
    ②从71H读出2号单元的内容

4.CMOS RAM中存放的时间信息
存放时间:年、月、日、时、分、秒。这6个信息的长度都是1个字节。

  1. SHL是逻辑左移指令,它的功能为:
    [1]将一个寄存器或内存单元的数据向左移位;
    [2]将最后移出的一位写入CF;
    [3]最低位用0补充。
    SHR逻辑右移指令,它与SHL操作相反:
    [1]将一个寄存器或内存单元的数据向右移位;
    [2]将最后移出的一位写入CF;
    [3]最高位用0补充。

1.外设的输入不直接送入内存和CPU,而是送入相关的借口芯片的端口中;CPU向外设的输出也不是直接送入外设,而是先送入端口中,再由相应的芯片送到外设。可见,CPU通过端口和外部设备进行联系。

2.可屏蔽中断:可由标志寄存器IF位设置,如果IF=1,CPU在执行完当前指令后响应中断,引发中断过程;如果IF=0,则不响应中断。
Sti ,用于设置IF=1;
Cli 用于设置IF=0.
中断过程:1. 取中断类型码n

2. 标志寄存器入栈,IF=0,TF=0.
3. CS、IP入栈
4. (IP)=(N*4),(CS)=(N*4+2).

中断类型码是通过数据总线送入CPU 的。

3.键盘输入的处理:键盘中有一个芯片对键盘上的每一个键的开关状态进行扫描,按下一个键时,该芯片就产生一个扫描码,称为通码。扫描码被送入主板上的相关借口芯片的寄存器中,该寄存器的端口地址为60H。松开按下的键时,也产生一个扫描码,称为断码,也被送入60H。
断码=通码+80H
扫描码长度为一个字节,通码的第7位为0,断码的第7位为1.

4.键盘的输入到达60H端口时,相关的芯片就会向CPU发出中断类型码为9的可屏蔽中断信息。CPU检测到该中断信息后,如果IF=1,则响应中断,引发中断过程,转去执行int9中断例程。

5.BIOS提供了int9中断例程,用来进行基本的键盘输入处理,主要工作:
[1]读出60H端口中的扫描码;
[2]如果是字符键的扫描码,将该扫描码和它对应的字符码(ASCII码)送入内存中的BIOS键盘缓冲区;如果是控制键和切换键的扫描码,则将其转变成状态字节,写入内存中存储状态字的单元
[3]对键盘系统进行相关的控制,比如说,向相关芯片发出应答信息。
0040:17单元存储状态字节,该字节记录了控制键和切换键的状态。
0:右shift状态,置1表示按下
1:左shift状态,置1表示按下
2:ctrl状态,置1表示按下
3:alt状态,置1表示按下
4:scrolllock状态,置1表示scroll指示灯亮
5:Numlock状态,置1表示小键盘输入的是数字
6:capslock状态,置1表示输入大写字母
7:insert状态,置1表示出于删除态。

6.键盘输入的处理过程:
键盘产生扫描码——扫描码送入60H端口——引发9号中断——CPU执行INT9中断例程处理键盘输入。
前三步都是由硬件系统完成的。

7.简单延时函数
Mov dx,10h
Mov ax,0
S: sub ax,1
Sbb dx,0[1]
Cmp ax,0
Jne s
Cmp dx,0
Jne s
程序实现100000H次循环。

8.指令系统总结:
[1]数据传送指令:mov、push、pop、pushf、popf、xchg等,这些指令实现寄存器和内存、寄存器和寄存器之间的单个数据传送。
[2]算术运算指令:add、sub、adc、sbb。Inc、dec、cmp、imul、idiv、aaa等,这些指令实现寄存器和内存中的数据的算术运算,他们的执行结果影响标志寄存器的:sf、zf、of、cf、pf、af位
[3]逻辑指令:and、or、not、xor、test、shl、shr、sal、sar、rol、ror、rcl、rcr等,除了not指令外,其他的执行结果都影响标志寄存器的相关标志位。
[4]转移指令:可以修改IP,或同时修改CS和IP的指令:无条件转移指令——jmp;条件转移指令——jcxz、je、jb、ja、jnb、jna;环指令:loop;过程:call,ret,retf;中断:int,iret。
[5]处理机控制指令:这些指令对标志寄存器或其他处理机状态进行设置,如:cld std cli sti nop clc cmc stc hlt wait esc lock等
[6]串处理指令:这些指令对内存中的批量数据进行处理,比如,movsb movsw cmps scas lods stos等,若要使用这些指令方便地进行批量数据的处理,则需要和rep、repe、repne等前缀指令配合使用。

1.描述了单元长度的标号:
a db 1,2,3,4
B dw 0
Mov al,a[si]
Mov ah,0
Add b,ax
标号a、b是同时描述内存地址和单元长度的标号。标号a,描述了地址code:0,和从这个地址开始,以后的内存单元都是字节单元;而标号b描述了地址code:4,和从这个地址开始,以后的内存单元都是字单元。
标号a,b后面没有“:”
指令:mov ax,b
相当于:mov ax,cs:[4]
指令:mov al,b
指令会引起编译错误,因为b代表的是字单元,al是8位寄存器。

2.在其他段中使用数据标号:如果想在代码段中,直接用数据标号访问数据,则需要用伪指令assume将标号所在的段和一个段寄存器联系起来。否则编译器在编译的时候无法确定标号的段地址在哪一个寄存器中。

3.可以将功能子程序的入口地址存储在一个表中,他们在表中的位置和功能号相对应。对应的关系为:功能号*2=对应的功能子程序在地址表中的偏移。

0%