[BX]和loop指令
- [bx]也可以用来表示一个内存单元,偏移地址在bx中
- loop指令:loop标号,执行loop指令的时候,先执行(cx)=cx)-1,再判断cx的值,不为零则转到标号处,否则向下执行
- 【debug】[-g ip]指令:直接跳转到指定的ip指令处
- 【debug】[-p]指令:跳出循环
- 汇编源程序中,如果使用指令访问内存单元,必须使用”[…]”来表示内存单元,如果使用常量直接给出偏移地址,需要在”[]”前面显式给出段地址所在的段寄存器,例如
mov al,ds:[0]
- 如果在”[…]”中使用寄存器,则段地址默认在ds中
包含多个段的程序
- dw(define word):定义字型数据
- 如果需要cpu从何处开始执行程序,只需要在源程序中使用”end 标号”指明就可以了
- 在程序中,段名可以表示标号,代表段地址
更灵活的定位内存地址的方法
- and, or指令
mov al,01100011B | and(or) al,00111011B
- 使用[bx+idata]的方式进行数组的处理
数据处理的两个基本问题
- 8086CPU中,只有bx,si,di,bp可以使用在”[…]”中进行内存单元的寻址
- 上述的4个寄存器可以单个出现或者以下面4种组合出现:bx和si,bx和di,bp和si,bp和di
- 只要在[…]中使用寄存器bp,而指令中没有显性地给出段地址,段地址就默认是ss
- 在没有寄存器名存在的情况下,使用[X ptr]来指明内存单元的长度,这里X可以为word或者byte
转移指令的原理
- 可以修改IP,或同时修改CS和IP的指令统称为转移指令
- 转移指令可以控制CPU执行内存中的某处代码
- 段内转移:
jmp ax
段间转移 jmp 1000:0
- 短转移:-128~127 近转移-32768~32768
- offset可以取得标号的偏移地址,如
mov ax,offset start
- nop的机器码占一个字节
jmp short(8位位移) 标号
jmp near(16位位移) 标号
- cpu在执行jmp段内指令的时候并不需要转移的目的地址,包含的是转移的位移
jmp far ptr 标号
段间转移(远转移)jmp word ptr 内存单元地址(段内转移)
jmp dword ptr 内存单元地址(段间转移)
高地址是转移的目的段地址,低地址处是转移的目的偏移地址jcxz 标号
条件转移指令,所有的条件转移指令都是短转移jcxz 标号
如果(cx)=0,转移到标号处执行- loop为循环指令,所有的循环指令都是短转移
call和ret指令
- ret指令使用栈中的数据来修改IP,实现近转移 –>
pop ip
- retf指令只用栈中的数据修改CS和IP的内容,实现远转移 –>
pop ip
pop cs
- call指令将当前的ip或cs和ip压入栈中,再执行转移,需要注意的是不能进行短转移
- call执行[call 标号],相当于
push ip
jmp near ptr 标号
- [call far ptr 标号]实现的事段间转移,相当于
push cs
push ip
jmp far ptr 标号
- [call 16位reg],相当于
push ip
jmp 16位reg
- [call word ptr 内存单元地址],相当于
push ip
jmp word ptr 内存单元地址
- [call dword ptr 内存单元地址],相当于
push cs
push ip
jmp dword ptr 内存单元地址
- cpu读取ip值以后更改ip,再执行已经放入指令缓冲期中的指令
- call指令再转去执行子程序之前,call指令后面的指令的地址将存储在栈中,所以可以在自程序的后面使用ret指令,用栈中的数据设置ip的值,从而转到call指令后面的代码处继续执行,模版如下:
assume cs:code
code segment
main: :
:
call sub1
:
mov ax,4c00h
int 21h
sub1: :
call sub2
:
ret
sub2: :
:
ret
code ends
end main
- (al) * num8 = [ax]; (ax) * num16 = [dx:ax]
- [mul reg]
- [mul byte ptr ds:[0]]
- [mul word ptr ds:[0]]