汇编学习笔记(三)
在汇编源程序中,数据不能以字母开头,所以要在前面加0。如,9100h可以直接写为9100h
,而A000h则要写为0A000h
程序加载后,ds中存放着程序所在内存的段地址,偏移地址是0。这个内存区前256个字节存放着的是PSP,DOS用来和程序进行通信,所以程序的地址可以表示为DS+10H:0
and是逻辑与命令,or是逻辑或命令。
大小写转换:一个字母,无论是大小写,将它的第5位置0,就变成大写,第5位置1,就变成小写。
si和di是8086中与bx功能相近的寄存器,si和di不能分成2个8位寄存器。
一般来说,在需要暂存数据的时候,我们都应该使用栈。
bx,si,di,bp
- 在8086中,只有这4个寄存器可以用在
[...]
中来进行内存单元的寻址。 - 在
[...]
中,这4个寄存器可以单独出现,或只能以4种组合出现:
1.bx和si
2.bx和di
3.bp和si
4.bp和di - 只要在
[...]
中使用bp,而指令中没有显性给出段地址,那么段地址就默认在ss
中。
数据在什么地方?
1.立即数:在CPU的指令缓存器中,如:mov ax,1
2.寄存器:在寄存器中,如:mov ax,bx
3.段地址(SA)和偏移地址(EA),如:mov ax,[0]
(段地址默认是ds),mov ax,[bp]
(段地址默认是ss)
数据有多长?
数据有2种尺寸:byte和word
1.通过寄存器名指明要处理的数据的尺寸。
如指明进行字操作:
mov ax,1
mov ds:[0],ax
指明进行字节操作:
mov al,1
mov ds:[0],al
2.在没有寄存器名的情况下,用操作符X ptr
指明内存单元的长度,X可以为word
或byte
。如:
用word ptr
指明了指令访问的内存单元是一个字单元:
mov word ptr ds:[0],1
inc word ptr [bx]
用byte ptr
指明是一个字节单元:
mov byte ptr ds:[0],1
inc byte ptr [bx]
3.有些指令默认了访问的是字单元还是字节单元,如,push [1000H]
,push只进行字操作。
div
div是除指令,要注意一下问题:
- 除数:8位和16位两种,在一个寄存器或内存单元中。
- 被除数:默认放在AX或DX和AX中,如果除数为8位,被除数位16位,默认放在AX中;如果除数为16位,被除数为32位,在DX和AX中存放,DX存高16位,AX存低16位。
- 结果:如果除数为8位,则AL存储除法操作的商,AH存储除法操作的余数;如果除数为16位,则AX存放商,DX存放余数。
格式:
div 寄存器
div 内存单元
div byte ptr ds:[0]
含义:(al)=(ax)/((ds)*16+0)的商
(ah)=(ax)/((ds)*16+0)的余数
div word ptr es:[0]
含义:(ax)= [(dx)*10000H+(ax)] /((es))*16+0)的商
(dx)= [(dx)*10000H+(ax)] /((es))*16+0)的余数
伪指令dd
- db:用来定义字节型数据
- dw:用来定义字型数据
- dd:用来定义双字(define double word)型数据
dup
dup是一个操作符,它是和db,dw,dd配合使用的。如:
db 3 dup (0)
定义了3个字节,值都是0,相当于db 0,0,0
使用格式:
db 重复的次数 dup (重复的字节型数据)
dw 重复的次数 dup (重复的字型数据)
dd 重复的次数 dup (重复的双字型数据)
转移指令的原理
可以修改IP,或同时修改CS和IP的指令统称为转移指令。转移指令就是可以控制cpu执行内存中某处代码的指令。
8086的转移行为有以下几类:
- 只修改IP,称为段内转移,如:
jmp ax
- 同时修改CS和IP,称为段间转移,如:
jmp 1000:0
段内转移又分为短转移和近转移:
- 短转移IP的修改范围为-128~127
- 近转移IP的修改分为为-32768~32767
转移指令有以下几类:
- 无条件转移(如:jmp)
- 条件转移
- 循环转移(如:loop)
- 过程
- 中断
这些转移的前提条件可能不同,但原理都相同。
offset
由编译器处理,功能是取得标号的偏移地址。
start: mov ax,offset start ;相当于 mov ax,0(0是start的偏移地址)
s: mov ax,offset s ;相当于 mov ax,3(3是s的偏移地址)
jmp指令
jmp可以只修改IP,也可以修改同时CS和IP
jmp指令要给出两种信息:
1.转移的目的地址
2.转移的距离
依据位移进行转移的jmp指令
jmp short 标号
(转到标号处),short指明是段内短转移(8位位移),所对应的机器码并不包含转移的目的地址,而是包含的转移的位移
cpu在指令jmp指令的时候,并不需要知道转移的目标地址。
类似的,有jmp near ptr 标号
,实现的是段内近转移(16位位移)。
位移 = 标号处的地址 - jmp指令后的第一个字节的地址。
依据转移的目的地址进行转移的jmp指令
jmp far ptr 标号
实现的是段间转移,又称远转移
功能:(cs)= 标号所在段地址,(ip)= 标号在段中的偏移地址
机器码中有转移的目的地址
转移地址在寄存器中的jmp指令
格式:jmp 16位寄存器
功能:(ip)= (16位寄存器)
转移地址在内存中的jmp指令
有两种:
-
jmp word ptr 内存单元地址(段内地址)
功能:从内存单元地址处开始存放着一个字,是转移的目的偏移地址。
如:
mov ax,0123H
mov [bx],ax
jmp word ptr [bx]
执行后,(IP)= 0123H
2.jmp dword ptr 内存单元地址(段内地址)
功能:从内存单元地址处开始存放着两个字,高地址是转移的目的段地址,低地址是转移的目的偏移地址。
如:
mov ax,0123H
mov [bx],ax
mov word ptr [bx+2],0
jmp dword ptr [bx]
执行后,(CS)= 0,(IP)= 0123H
注意:形如
jmp 2000:1000
的转移指令,是在Debug中使用的汇编指令,汇编编译器并不认识,如在源程序中使用,将编译报错。
jcxz指令
为有条件转移指令,所有的有条件转移指令都是短转移,相应机器码都是包含的位移,而不是目的地址。
格式:
jcxz 标号(如果(cx)=0,转移到标号处执行)
操作:
当(cx)=0时,(ip)=(ip)+8位位移
相当于
if (cx==0)
jmp short 标号
loop指令
为循环指令,所有的循环指令都是短转移。
格式:
loop 标号((cx)= (cx)-1),如果(cx)!= 0,转移到标号处执行
操作:
1.(cx)=(cx)-1
2.如果(cx)!= 0 ,(ip)=(ip)+8位位移
相当于:
cx--;
if (cx!=0)
jmp short 标号;