• 转移指令的原理


    可以修改IP,或者同时修改cs和ip的指令统称为转移指令。
    8086cpu的转移行为有以下几类:

    • 只修改ip,称为段内转移,如jmp ax
    • 同时修改cs和ip,称为段间转移,如jmp 1000:0

    根据转移指令对于ip的修改范围不同,所以段内转移又分为:短转移和近转移

    • 短转移IP的修改返回为-128~127
    • 近转移IP的修改范围为-32768~32767

    8086cpu的转移指令分为以下几类:

    • 无条件转移指令(如:jmp)
    • 条件转移指令 (jcxz)
    • 循环指令(loop)
    • 过程
    • 中断

    不同转移指令的转移条件可能不同,但是转移的基本原理是相同的

    操作符offset

    offset是在汇编语言中是由编译器处理的符号,功能为取得标号的偏移地址。也就是相对于代码段的偏移地址,就是直接IP值了。

    jmp指令

    jmp为无条件转移指令,可以只修改IP,也可以同时修改cs和ip。
    jmp指令需要给出两种信息:

    • 转移的目的地址
    • 转移的距离(段间转移,段内短转移,段内近转移)

    不同的给出目的地址的方法不同,和不同的转移位置,对应有不同格式的jmp指令。

    依据位移进行转移的jmp指令

    1. jmp short 标号 (IP)=(IP)+8位位移
      这种格式的jmp指令实现的是段内短转移。对ip的修改范围限定为-128~127之间,可以看出正好是一个字节能够表示的范围。
    2. jmp near ptr 标号 (IP)=(IP)+16位位移
      jmp short功能相同,只不过他实现的是段内近转移。简单来说就是转移的距离拉长(虽然仍然是在段内)

    小贴士
    可以看到jmp shortjmp near ptr(段内转移)并没有直接将转移的目的地址直接写入机器指令中。而是将一个相对偏移地址写入了机器指令。(但是debug在对应的汇编指令中会看到偏移地址)
    具体来说就是将标号地址相对于jmp指令的下一条指令的地址写入了机器指令。
    也就是说,cpu在执行jmp指令的时候并不需要转移的目标地址。
    UTOOLS1561367196752.png

    转移的目的地址在指令中的jmp指令

    前面讲到的段内转移指令其机器指令中并没有转移的目的地址,而是相对于当前ip的转移位移。
    jmp far ptr 标号实现段间转移,又称为远转移。
    (CS)=标号所在段的段地址;(IP)=标号在段中的偏移地址
    far ptr将标号的地址写入了汇编指令。
    UTOOLS1561367856893.png

    jmp指令的机器码为EA,可以很明显的看出来,其中高地址放段地址,低地址放偏移地址。
    顺便说明,像是jmp 1000:0是在debug中使用的,在汇编代码中并不能使用这样的指令。

    转移地址在寄存器中的jmp指令

    指令格式: jmp 16位reg
    功能: (IP)=(16位reg)

    转移地址在内存中的jmp指令

    转移地址在内存中的jmp指令有两种格式:

    1. jmp word ptr 内存单元地址(段内转移)
      更改ip值。
    2. jmp dword ptr 内存单元地址(段间转移)
      目标内存中放着两个字,其中高地址处的字为转移目标的段地址,低地址处的字为转移的目标的段偏移地址。
      (CS)=(内存单元地址+2)
      (IP)=(内存单元地址)

    jcxz指令

    jcxz为条件转移指令。所有的条件转移指令都是短转移指令,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围为-128~127.
    功能:当cx寄存器的值为0是执行转移,否则什么也不做。

    loop指令

    loop指令为循环指令,所有的循环指令都是短转移。

    根据位移进行转移的意义

    高端大气的说法就是方便了程序段在内存中的浮动装配
    实际上就是无所谓程序在内存中的地址,程序中的转移指令无需改变。

    编译器对于转移位移超界的检测

    根据位移进行转移的指令,他们的转移范围收到转移位移的限制,如果在源程序中出现了转移范围超界的问题,在编译的时候,编译器将会报错。

    分析一个奇怪的程序

    就是一个计算通过相对偏移位置计算偏移位置的问题。
    UTOOLS1561372732806.png

    会注意到在执行完mov cs:[di], ax以后,s段的9090(nop nop)变成了EBF6(值为F6EB【小端序】)。同时想到的是同样都是EBF6却翻译出了不同的汇编指令。然而实际上都是相同的,翻译的问题是编译器做的。他将机器码翻译了以下,也就是将相对偏移地址直接翻译成为了IP中的偏移地址。
    即使上面讲到过的偏移地址=jmp的下一条指令地址+相对偏移地址(注意到F6的问题,计算机中的数据以补码方式存储)。他就是将偏移地址算了出来。

    根据材料编程

    答案:

    assume cs:code, ds:data
    data segment
     db 'welcome to masm!' ; 文字
     db 00000010B, 00100100B, 01110001B ; 属性
    data ends
    
    code segment
    start:
     mov ax, data
     mov ds, ax
    
     mov ax, 0b800H 
     mov es, ax 
    
     mov bx, 0
     mov si, 0
     mov di, 64
     mov bp, 6e0H 
    
     mov cx, 3
    ln: 
     mov dx, cx
     mov cx, 16
    
     mov bx, 0
     mov di, 64
    s:
     mov al, [bx]
     mov ah, 16[si]
     mov es:[bp].[di], ax
    
     inc bx
     add di, 2
     loop s
    
     add si, 1
     add bp, 160
     mov cx, dx
     loop ln
    
     mov ax, 4c00H
     int 21H
    
    code ends
    end start

    注意数值不能以字母开头





  • 相关阅读:
    [整理]Cadence 生成带有网络追踪的 PDF 原理图
    [整理]FSM 有限状态机
    [原创]Quartus 中调用 Modelsim 波形仿真
    [原创]SPI 协议介绍以及基于 Verilog 的 IP 核实现
    [原创]Verilog 代码编程规范(个人用)
    [算法]线段树
    [算法]tarjan
    poj3280
    poj 3258 River Hopscotch
    [poj 1251]Jungle Roads
  • 原文地址:https://www.cnblogs.com/freesfu/p/11078810.html
Copyright © 2020-2023  润新知