• 汇编学习--第八天


    第九章 转移指令的原理

    8086CPU的转移行为分类:

    第一种分类:

    1. 只修改IP---段内转移,jmp ax
    2. 同时修改IP和CS--段间转移。jmp 1000:0

    第二种分类

    1. 短转移IP修改范围:-128~127
    2. 近转移IP修改范围:-32768~32767

    转移指令分类:

    1. 无条件转移指令(jmp)
    2. 条件转移指令
    3. 循环指令
    4. 过程
    5. 中断

    9.1 操作符offset

    获取标号的偏移地址

    assume cs:codesg
    codesg segment
    start:    mov ax,offset start  ;相当于mov ax,0
    s:        mov ax,offset s    ;相当于mov ax,3
    codesg ends
    end start

    问题 9.1

    mov ax,cs:[si]

    mov cs:[di],ax

    nop的机器码占一个字节

    assume cs:codesg
    codesg segment
    start:    mov bx,ax
            mov si,offset start
            mov di,offset s
            mov ax,cs:[si]
            mov cs:[di],ax        
    s:        nop
            nop
            mov ax,4c00h
            int 21h
    codesg ends
    end start

    9.2 jmp指令

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

    下面jmp,jcxz类似的跳转操作的范围,都是使用补码表示。

    jmp根据表示的位置是指:8位位移=标号处地址-jmp后的第一个字节的地址(也就是第一条指令)

    assume cs:codesg
    codesg segment
    start:    mov ax,0
            jmp short s
            add ax,2
    s:        inc ax
            
            mov ax,4c00h
            int 21h
    codesg ends
    end start

    EB03=0008-0005

    assume cs:codesg
    codesg segment
    start:    mov ax,0
            jmp short s
            add ax,2
    s:        inc ax
            jmp start
            
            mov ax,4c00h
            int 21h
    codesg ends
    end start

    EB03=0008-0005

    EBF5=0000-0000B=-B(补码表示)=10001011=11110101=245=F5

    jmp near ptr

    段内近转移

    (IP)=(IP)+16

    jmp根据表示的位置是指:16位位移=标号处地址-jmp后的第一个字节的地址(也就是第一条指令)

    位移范围为:-32768~32767

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

    jmp far ptr

    段间转移,远转移

    (CS)=标号所在段的段地址;(IP)=标号在段中的偏移地址

    assume cs:codesg
    codesg segment
    start:    mov ax,0
            mov bx,0
            jmp far ptr s
            db 256 dup(0)
    s:        add ax,1
            inc ax
            
            mov ax,4c00h
            int 21h
    codesg ends
    end start

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

    jmp word ptr 内存单元地址(段内转移)

    将IP的值设为转移地址中的值

    assume cs:codesg
    codesg segment
    start:    mov ax,0123h
            mov ds:[0],ax
            jmp word ptr ds:[0]
            
            mov ax,4c00h
            int 21h
    codesg ends
    end start

    jmp dword ptr

    从内存地址处开始存放两个字,高地址处是转移的目的段地址(CS),低地址处是转移的目的偏移地址。

    (CS)=(内存单元地址+2)

    (CS)=(内存单元地址)

    assume cs:codesg
    codesg segment
    start:    mov ax,0123h
            mov ds:[0],ax
            mov word ptr ds:[2],0
            jmp dword ptr ds:[0]
            
            mov ax,4c00h
            int 21h
    codesg ends
    end start

    mov word ptr ds:[2],0实际上是把一个字存放到 内存地址+2处,下面ptr再写入CS:IP

    相当于

    mov ax,0
    mov ds:[2],ax

     检测点 9.1

    (1)我想的这道题就是令IP=0就行,也就是ds:[bx+1]处的值要为0

    assume cs:codesg
    datasg segment
        dw 5 dup (0)
    datasg ends
    codesg segment
    start:    mov ax,datasg
            mov ds,ax
            mov bx,0
            jmp word ptr [bx+1]
            
            mov ax,4c00h
            int 21h
    codesg ends
    end start

    (2)

    这道和上面一样的思想,不过多了一个更改CS段地址,段地址可以根据datasg段来算

    我们得到,DS=075AH,所以程序的地址是076AH

    从已经给出的代码中,我们得到datasg段占4个字节,不满16字节(一行),但是在系统中还是占一行。

    所以,我们推出程序代码的起始地址在076BH

    assume cs:codesg
    datasg segment
        dd 12345678h
    datasg ends
    codesg segment
    start:    mov ax,datasg
            mov ds,ax
            mov bx,0
            add ax,1
            mov [bx],bx
            mov [bx+2],ax
            jmp dword ptr ds:[0]
            
            mov ax,4c00h
            int 21h
    codesg ends
    end start

    (3)

    assume cs:codesg
    codesg segment
    start:    mov ax,2000h
            mov es,ax
            mov ax,00beh  ;题中是之前在2000:0就有数据,我是0000...,只能自己动手丰衣足食了。
            mov es:[1000h],ax
            mov ax,0006h
            mov es:[1002h],ax
            jmp dword ptr es:[1000h]
            
            mov ax,4c00h
            int 21h
    codesg ends
    end start

    9.7 jcxz指令

    短转移,格式“jcxz 标号”

    先判断cx,再cx自减

    当cx==0时,跳转到标号处

    检测点 9.2

    assume cs:codesg
    codesg segment
    start:    mov ax,2000h
            mov ds,ax
            mov bx,0
            
            mov al,'b'
            mov ds:[bx],al
            mov al,'i'
            mov ds:[bx+1],al
            
    s:        mov cl,[bx]
            mov ch,0
            jcxz s0
            inc bx
            loop s
            
    s0:        mov dx,bx
            mov ax,4c00h
            int 21h
    codesg ends
    end start

    9.8 loop指令

    loop指令类似于jcxz,不过是cx!=0时,进行跳转标号处。

    cx先自减,再判断

    检测点 9.3

    dec bx ;和inc相反,自减一

    inc cx

    9.9 根据位移进行转移的意义

     两种,相当于绝对位置和相对位置的区别。

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

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

    可以

    assume cs:codesg
    codesg segment
            mov ax,4c00h
            int 21h
            
    start:    mov ax,0
    s:        nop
            nop
            
            mov di,offset s
            mov si,offset s2
            mov ax,cs:[si]
            mov cs:[di],ax
            
    s0:        jmp short s
    
    s1:        mov ax,0
            int 21h
            mov ax,0
            
    s2:        jmp short s1
            nop
            
    codesg ends
    end start

    注意红色部分的变化

    在我们运行指令时,会发现运行到jmp short s之后,会运行jmp 0000,而原本应该跳到s标号处执行NOP,也就是说s处的指令发生的变化。

    产生这种变化的原因,我们可以理解

            mov di,offset s
            mov si,offset s2
            mov ax,cs:[si]
            mov cs:[di],ax

    这里实际上是将,标号s2处的指令移动到了s处,而jmp跳转地址是根据偏移地址改变的,在s处被替换的指令偏移位置,是s2处的偏移量。

    s2处偏移量为18H-22H=-AH,因为jmp指令占两个内存单元空间,所以s处两个nop变成一条jmp指令,也就是从076A:000AH处,向上移动AH,也就是0,所以在跳转到s处,会显示jmp 0000,进而执行返回指令。

  • 相关阅读:
    cf1011 E. Border
    cf 1011 D. Rocket
    cf 1011C. Fly
    cf 1015 E2. Stars Drawing (Hard Edition)
    cf 1015 E1. Stars Drawing (Easy Edition)
    Walking Between Houses(Codeforces-1015D)
    D. Vasya And The Matrix 构造
    点击数据将之前信息隐藏显示当前(手机端页面)
    连接返回上一步(上一个页面)
    公共的css样式
  • 原文地址:https://www.cnblogs.com/Mayfly-nymph/p/11104494.html
Copyright © 2020-2023  润新知