汇编语言-笔记-第九章及实验8

第9章 转移指令的原理
一、8086转移指令的分类
1、无条件转移指令,如jmp;
2、条件转移指令,如jcxz;
3、循环指令,如loop;
4、过程;

5、中断

二、几种转移指令的详解
*基础知识:补码
在计算机系统中,数值一律用补码来表示(存储)。正数补码与原码相同,如十进制17;原码为0001 0001;其补码也为0001 0001;
负数的补码最高位取1,剩余7位为将负数取绝对值按位取反后+1,得其补码(对8位补码)。如-1;最高位取1,绝对值7位为0000001,按位取反后为1111110;+1后为1111111;则-1的补码为11111111.
也可知,对8位补码,其可表示的数值范围为-128~127;对16位补码其表示范围为-32768~32767.

*offset操作符:offset 标号 表示:获取标号位置处的偏移地址。


1、段内短转移:jmp short 标号
其仅对ip值进行修改;修改范围是-128~127(往前128个字节,往后127个字节);
在机器码中,jmp short 标号对应的是使用位移来寻址,该语句告诉CPU的并不是目的地址,而是基于当前ip的位移量。
如下指令及设其ip对应如下:
mov ax,0--------IP:a1
mov bx,0--------IP:a1+3
jmp short s--------IP:a1+6
add ax,1--------IP:b1
s:add ax,2--------IP:b2
当ip=a1+6时候,CPU读取jmp short s进入指令缓冲区;ip指向下一条指令,即ip=b1;然后执行jmp short s;执行完毕后指令指向标号s处,即ip=b2;其位移量为(b2-b1);通过上述分析可知,位移量应为(目标偏移地址减去jmp指令下一条指令的偏移地址)。
也因此,jmp short s的功能为:(IP)=(IP)+8位位移量(位移量的计算是在编译过程中计算出的)。以上例具体来说位移量为b2-b1.而执行完jmp指令后的ip=b1;即新的(ip)=b2-b1+b1=b2。
2、段内近转移:jmp near ptr  标号;
其功能与段内短转移类似,表达为:(IP)=(IP)+16位位移量
3、不使用位移量转移而直接指定转移目的地址的jmp指令
(1)转移目的地址在指令中的jmp指令
段间转移(远转移):jmp far ptr 标号
表达为:(CS)=标号所在段的段地址;(IP)=标号所在位置的偏移地址。

(2)转移地址在寄存器中的jmp指令:jmp 16位reg
表达为:(IP)=(16位reg)
(3)转移地址在内存中的jmp指令:jmp word/dword ptr 内存单元地址
如:jmp word ptr ds:[0]
功能为:CS不变,(IP)=(ds:[0])
如:jmp dword ptr ds:[0]
功能为:(CS)=(ds:[2]),(IP)=(ds:[0])
4、条件转移指令:jcxz 标号
表达为:if((cx)==0) jmp short 标号
注意:所有的条件转移均为短转移。即位移量为-128~127.
5、循环指令loop 标号
表达为:
cx=cx-1;
if ((cx)!=0) jmp short 标号
注意:所有的循环转移也均为短转移。即位移量为-128~127.

三、通过位移量确定转移地址的几个指令

总共有4类,jmp型的有两种:

(1)jmp short  标号

(2)jmp near ptr 标号

另外等价的还有两种:

(3)jcxz 标号:等价于 if(!(cx))  jmp short 标号

(4)loop 标号:等价于:先(cx)=(cx)-1;再if((cx)) jmp short标号 

检测点9.1

(1)要使程序中jmp指令执行后,cs:ip指向程序第一条指令,data段该如何定义。

分析:jmp word ptr []使用的是直接给出偏移地址,即这里ds:[bx+1]的值要为0.

对于data段来说,就是第二个内存单元值为0,对其他无所谓。

assume cs:code
data segment
    db  0,0
data ends

code segment
    start:mov ax,data
          mov ds,ax
          mov bx,0
          jmp word ptr [bx+1]
code ends

(2)补全程序,使得jmp执行后,cs:ip指向程序第一条指令。

分析:jmp  dword ptr ds:[0]设置的是(cs)=(ds:[2]);(ip)=(ds:[0])。

assume cs:code

data segment
dd 12345678H
data ends
code segment
    start: mov ax, data
    mov ds, ax
    mov bx, 0
    mov [bx],bx      
    mov [bx+2], cs
    jmp word ptr ds:[0]
    
    mov ax, 4c00h
    int 21h
code ends
end start

检测点9.2

补全程序,利用jcxz指令,在内存2000H段中查找第一个为0的单元,将其偏移地址存储在dx中。

assume cs:code
 
code segment
 
start:mov ax,2000h
 
        mov ds,ax
 
        mov bx,0
 
s:
        mov cl,ds:[bx];
        mov ch,0;
        jcxz ok;
        inc bx;      
 
        jmp short s 
 
ok:
        mov dx,bx

        mov ax ,4c00h
        int 21h
 
code ends
 
end start         

检测点9.3

补全程序,利用loop指令,实现在内存2000H段中查找第一个为0的单元,将其偏移地址存储在dx中。

assume cs:code
code segment
start:
           mov ax,2000H
           mov ds,ax
           mov bx,0
s:
           mov cl,[bx]
           mov ch,0
           inc cx          ;自增1满足loop跳出条件
           inc bx
           loop s            
           
ok:
           dec bx           
           mov dx,bx

           mov ax,4c00h
           int 21h
code ends
end start

实验8 分析一个奇怪的程序

assume cs:codesg
codesg segment
    mov ax,4c00h     ;A
    int 21h         ;B

start
    mov ax,0        
s:
    nop              ;C
    nop         ;D

    mov di,offset s  ;E
    mov si,offset s2
    mov ax,cs:[si]
    mov cs:[di],ax   ;把s2处的jmp short s1代码复制到s处,而该jmp代码实质是偏移-(x+2)个字节单位。

s0:
    jmp short s
s1:
    mov ax,0
    int 21h
    mov ax,0         ;设s1开始的这三句占据x字节
s2:
    jmp short s1     ;这句jmp本身占据2字节,则此处实质偏移量为-(x+2)
    nop

codesg ends
end start
;先从start入口开始执行,到F处执行完成后就是使得s标号处的代码变成了jmp指令
;继续往下执行到s0标号处,执行完跳转到标号s处
;此时s处的代码已经更新为jmp指令,该指令实质为往前偏移(x+2)个单元。
;可以看出A到E中间的代码长度和s1到s2处的nop的长度是一样的。所以执行s处的代码后,跳转到A处
;执行A,B;退出程序返回

   
原文地址:https://www.cnblogs.com/tsembrace/p/3267145.html