可以修改IP,或同时修改CS和IP的指令统称为转移指令。只修改IP的指令是段内转移(包括短转移和近转移),同时修改IP和CS的称为段间转移。
一、依据位移进行转移的jump指令
段内短转移:jump short 标号
实际功能:IP = IP + 8位位移
(1)8位位移 = 标号处的地址 - jump指令后的第一个字节位置
(2)位移范围为-128~127,用补码表示
段内近转移:jump near ptr 标号
实际功能:IP = IP + 16位位移
它与段内段转移相比,只是位移的偏移量范围更大了些。
段间转移,又称远转移:jump far ptr 标号
CS = 标号处的段地址, IP=标号处的偏移地址
注意:此处已不是位移了,而是绝对地址
jump 16位 reg
功能:IP = 16位 reg
jump word ptr 内存中单元地址 (段内转移)
jump dword ptr 内存中单元地址 (段间转移)
二、其它指令
有条件转移指令,所有有条件转移指令都是段内短转移,所以在相应的机器码中包含的是转移位移,而不是目的地址。
指令格式:jcxz 标号
执行:如果cx==0,则执行标号处的代码,否则什么也不做
if(cx==0){jump short 标号}
loop指令
loop指令是循环指令,所有循环指令都是段内短转移。
格式:loop 标号
cx = cx - 1;
if(cx != 0 ){jump short 标号}
根据位移进行转移的指令,转移的范围是受到限制的,如果代码中的转移范围超出了范围,这种错误在编译的过程中就能够由编译器检测出来。
三、一个奇怪的程序
实例:
assume cs:code
code segment
mov ax,4c00h ;0-2
int 21h ;3-4
start: mov ax,0 ;5-7
s: nop ;8
nop ;9
mov di,offset s ;a-c 8
mov si,offset s2 ;d-f 20
mov ax,cs:[si] ;10
mov cs:[di],ax ;11-12,13,14-15
s0: jmp short s ;16,17
s1: mov ax,0 ;18-1a
int 21h ;1b-1c
mov ax,0 ;1d-1f
s2: jmp short s1 ;20-21 18
nop ;22
code ends
end start
四、实例:根据材料编程
在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串“welcome to masm!”
屏幕中间意味着:行11-13,列32-47
assume cs:code,ds:data
data segment
db 'welcome to masm!' ;要显示的16个ascii字符
db 2,24h,70h ;每行字符的属性值
data ends
code segment
start: mov ax,data
mov ds,ax ;初始化数据段段地址
mov ax,0b800h
mov es,ax ;初始化屏幕数据段的段地址,数据均写入到es寄存器代表的段地址内
mov cx,3
mov si,10h ;[si]指向ds:[10],在外层循环中每次加1,则[si]始终代表输出到屏幕的当前行的ascii字符的属性,属性就从这里读取即可
mov bp,0
s: push cx
mov bx,0 ;ascii值从[bx]中读取,在内存循环开始前每次都置零,每次递增1
mov di,0
mov cx,16
s0: mov al,[bx] ;从ds:[bx]中按字节读取ascii字符到al中
mov es:[bp+di+720h],al ;将读取到的ascii字符写入到es:[bp+di+720h]中
mov al,[si] ;从ds:[si]中按字节读取属性值到al中
mov es:[bp+di+721h],al ;将读取到的属性值写入到es:[bp+di+721h]中
inc bx
add di,2
loop s0
;[bp+di+6e0h+40h] [bp+di+720h] [bp+di+720h+1]
;bp = bp + 0a0h
;di = di +2
pop cx
inc si
add bp,0a0h
loop s
mov ax,4c00h
int 21h
code ends
end start