实验三 转移指令跳转原理及其简单应用编程

实验任务1

程序源代码:

assume cs:code, ds:data

data segment
    x db 1, 9, 3
    len1 equ $ - x

    y dw 1, 9, 3
    len2 equ $ - y
data ends

code segment
start:
    mov ax, data
    mov ds, ax

    mov si, offset x
    mov cx, len1
    mov ah, 2
 s1:mov dl, [si]
    or dl, 30h
    int 21h

    mov dl, ' '
    int 21h

    inc si
    loop s1

    mov ah, 2
    mov dl, 0ah
    int 21h

    mov si, offset y
    mov cx, len2/2
    mov ah, 2
 s2:mov dx, [si]
    or dl, 30h
    int 21h

    mov dl, ' '
    int 21h

    add si, 2
    loop s2

    mov ah, 4ch
    int 21h
code ends
end start

运行截图:

      回答问题1


loop指令对应的机器码是(E2F2)16,其中(F2)16是补码表示的偏移量,换算成十进制数是-14。当前loop指令的长度是2字节,下一条指令的偏移地址是(001B)16,减去(14)10刚好是标号s1对应的偏移地址(000D)16.

      回答问题2

与问题1相似,机器码中偏移量的补码是(F0)16,对应十进制-16。下一条指令的偏移地址是(0039)16,减(16)10得标号s2的偏移地址(0029)16.

实验任务2

源程序代码:

assume cs:code, ds:data

data segment
    dw 200h, 0h, 230h, 0h
data ends

stack segment
    db 16 dup(0)
stack ends

code segment
start:  
    mov ax, data
    mov ds, ax

    mov word ptr ds:[0], offset s1
    mov word ptr ds:[2], offset s2
    mov ds:[4], cs

    mov ax, stack
    mov ss, ax
    mov sp, 16

    call word ptr ds:[0]
s1: pop ax

    call dword ptr ds:[2]
s2: pop bx
    pop cx

    mov ah, 4ch
    int 21h
code ends
end start

回答问题:

从理论上分析,ax中是标号s1的偏移地址,bx中是标号s2的偏移地址,cx中是标号s2的段地址。

注意到两条call指令一个是短转移一个是远转移。执行第一个call时,将当前命令的下一条命令的偏移地址(IP)压入栈,也就是将标号s1的偏移地址压入栈;随后(IP)变为内存单元偏移地址为0的字单元中的数值,由于程序已经将该字单元赋值为标号s1的偏移地址,所以程序看起来就是顺序执行了下面的命令而没有进行跳转,将刚刚压入栈的偏移地址弹出给寄存器ax;执行第二条远转移call时,依次将下一条指令的段地址(CS)和偏移地址(IP)压入栈,后面的过程与之前类似。

实验截图:

实验任务3

源程序代码:

assume cs:code, ds:data

data segment
    x db 99, 72, 85, 63, 89, 97, 55
    len equ $- x
data ends

code segment
start:
    mov ax, data
    mov ds, ax
    mov si, 0
    mov cx, len
    s:
    mov ah, 0
    mov al, [si]
    inc si
    call printNumber
    call printSpace
    loop s

    mov ah, 4ch
    int 21h

printNumber:
    mov bl, 10
    div bl
    mov bx, ax
    mov ah, 2
    add bl, 48
    mov dl, bl  ;商
    int 21h

    add bh, 48
    mov dl, bh  ;余数
    int 21h
    ret

printSpace:
    mov ah, 2
    mov dl, 32 ;空格的ASCII码	
    int 21h
    ret

code ends
end start

测试截图:

实验任务4

源程序代码:

assume cs:code, ds:data

data segment
    str db 'try'
    len equ $ - str
data ends

stack segment
    db 16 dup(0)
stack ends

code segment 
start: 
    mov ax, stack
    mov ss, ax
    mov sp, 16

    mov ax, data
    mov ds, ax
    mov si, 0     ;数据段偏移地址
    mov cx, len   ;字符串长度
    mov bh, 0     ;行号
    mov bl, 02h   ;黑底绿字
    call printStr 

    mov si, 0
    mov cx, len
    mov bh, 24
    mov bl, 04h   ;黑底红字
    call printStr

    mov ah, 4ch
    int 21h

printStr:
    mov ax, 0b800h
    mov es, ax
    push bx        ;暂存颜色
    mov bl, bh
    mov bh, 0      ;bx中现在是行号(0-24)
    mov ax, 00a0h  ;一行的字节数
    mul bx
    mov bx, ax     ;bx得到行首偏移地址
    pop ax
    mov ah, al

    s:
    mov al, [si]
    mov es:[bx+si], ax
    inc bx
    inc si
    loop s
    ret

code ends
end start

测试截图:

 

实验任务5

程序源代码:

assume cs:code, ds:data

data segment
    stu_no db '201983290485'
    len = $ - stu_no
data ends

code segment
start:
    mov ax, data
    mov ds, ax
    mov ax, 0b800h
    mov es, ax
    mov si, 1
    mov cx, 7d0h    ;2000次循环
    s:
    mov byte ptr es:[si],17h    ;00010111
    add si, 2
    loop s
 
    mov si, 0f00h
    mov cx, 80
    s1:
    mov byte ptr es:[si], 2dh  ;-----
    add si, 2
    loop s1

    mov si, 0f44h   ;最后一行中间
    mov cx, 12
    mov bx, 0
    s2:
    mov al, [bx]
    mov es:[si], al
    add si, 2
    inc bx
    loop s2

    mov ax, 4c00h
    int 21h 

code ends
end start

测试截图:

 

posted @ 2021-11-27 10:04  ww911911  阅读(62)  评论(2编辑  收藏  举报