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

发布时间:2022-06-28 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了实验3 转移指令跳转原理及其简单应用编程脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

1. 实验任务1

给出程序task1.asm源码,及运行截图

源码:

 1 assume cs:code, ds:data
 2 
 3 data segment
 4     x db 1, 9, 3
 5     len1 equ $ - x
 6 
 7     y dw 1, 9, 3
 8     len2 equ $ - y
 9 data ends
10 
11 code segment
12 start:
13     mov ax, data
14     mov ds, ax
15 
16     mov si, offset x
17     mov cx, len1
18     mov ah, 2
19  s1:mov dl, [si]
20     or dl, 30h
21     int 21h
22 
23     mov dl, ' '
24     int 21h
25 
26     inc si
27     loop s1
28 
29     mov ah, 2
30     mov dl, 0ah
31     int 21h
32 
33     mov si, offset y
34     mov cx, len2/2
35     mov ah, 2
36  s2:mov dx, [si]
37     or dl, 30h
38     int 21h
39 
40     mov dl, ' '
41     int 21h
42 
43     add si, 2
44     loop s2
45 
46     mov ah, 4ch
47     int 21h
48 code ends
49 end start

结果 

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

反汇编截图如下

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

 

 1

编译器通过标号处的地址-loop指令后的第一个字节的地址计算跳转的8位位移,此例中标号s1的偏移地址为000D,loop指令后第一个字节的偏移地址为001B,两者相减结果为-14,跳转的位移量为-14。

2

标号s2的偏移地址为0029,loop指令后第一个字节的偏移地址为0039,两者相减结果为-10。loop指令在内的所有循环指令都是短转移,对应机器码中包含转移位移而非地址,跳转的位移量是-10。

 2. 实验任务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  ; ds:[0] 存储了s1的地址
    mov word ptr ds:[2], offset s2  ; ds:[2] 存储了s2的地址
    mov ds:[4], cs                  ; ds:[4] 存储了当前段的段地址

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

    call word ptr ds:[0]            ; word为短转移,把 s1 处的 IP 进栈, 然后跳转到 s1 的地址
s1: pop ax                          ; 把 s1 处的 IP 值送入 ax

    call dword ptr ds:[2]           ; dword为远转移,把 s2 出的 CS:IP 值进栈, 然后跳转到 s2 处
s2: pop bx                          ; 把 s2 的 IP 值送入 bx
    pop cx                            ; 把 s2 的 CS 值送入 cx
    
    mov ah, 4ch
    int 21h
code ends
end start

给出分析、调试、验证后,寄存器(ax) = ? (bx) = ? (cx) = ? 附上调试结果界面截图。

① 根据call指令的跳转原理,先从理论上分析,程序执行到退出(line31)之前,寄存器(ax) =0021 寄存器(bx) =0026 寄存器(cx) =076C 

② 对源程序进行汇编、链接,得到可执行程序task2.exe。使用debug调试,观察、验证调试结果与理论分析结果是否一致。

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

 

 一致的,执行call指令时,程序会跳转到指定的地址处执行,同时把call指令后面一条指令的ip或cs,ip入栈。如图,执行call far [2]指令后,程序将076C和0026依次入栈。

3. 实验任务3

源码

assume ds:data, cs:code, ss:stack

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

stack segment
    dw 16 dup(?)
stack ends

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

    mov ax, stack
    mov ss, ax
    mov sp, 32

    mov cx, len ; 由于数据都是byte型,所以len就是数据个数
    ; print循环: 依次打印所有数字
    print:
        mov ah, 0                   ; 数据只有一个字节,先把ah置0,子函数中除法是以ax作为被除数的
        mov al, byte ptr ds:[di]    ; 把数据放入al
        inc di                      ; di指针后移

        push cx             ; 把cx保存起来, 子程序中会修改cx值

        call printNumber    ; 打印数字
        call printSpace     ; 打印空格

        pop cx              ; 恢复cx
    loop print
    
    mov ah, 4ch
    int 21h

; 子程序: printNumber
; 功能: 打印数字
;   入口参数: 
;       寄存器ax  (待输出的数据 --> ax)
;   局部变量说明: 
;       bx -> 存储数字字符个数
printNumber:
    mov bx, 0       ; 获取之前位数为0
    ; 逐位获取数字
    ; getEach循环: 获取每一位,然后压入栈中
    getEach:
        mov dl, 10      
        div dl          ; 数据除10

        push ax         ; 将数字压入栈中(ah余数在ax里了)
        inc bx          ; 位数+1
        
        mov ah, 0       ; ah是余数,置0后ax表示除法的结果
        mov cx, ax      ; 除法结果赋给cx, 如果结果为0则说明所有位数都获取完了
        inc cx          ; 由于loop时会-1,这里先+1,防止出现负数

    loop getEach

    ; 打印数字
    mov cx, bx          ; 先把bx存的数字位数赋给cx
    ; printEach循环: 依次从栈中取出数字,逐位打印
    printEach:
        pop ax          ; 取出一位数
        add ah, 30h     ; ah是刚才除法的余数,也就是需要得到的位数,+30h是转成对应字符
        mov dl, ah      ; 放到dl, 用于打印
        mov ah, 2       ; 调用int 21h的2号子程序打印
        int 21h
    loop printEach 

    ret

; 子程序: printSpace
; 功能: 打印空格
printSpace:
    mov ah, 2
    mov dl, 20h
    int 21h
    ret

code ends
end start

运行结果:

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

 

 4. 实验任务4

源码

 1 assume cs:code, ds:data
 2 data segment
 3     str db 'try'
 4     len equ $ - str
 5 data ends
 6 
 7 code segment
 8 start:
 9     mov ax, data
10     mov ds, ax
11 
12     mov si, offset str
13     mov bh, 0
14     mov bl, 2
15     call printStr
16 
17     mov si, offset str
18     mov bh, 24
19     mov bl, 4
20     call printStr
21 
22     mov ah, 4ch
23     int 21h
24 
25 printStr:mov cx, len
26   s:mov ax, 0b800h
27     mov dx, cx
28     mov ch, 0
29     mov cl, bh
30   t:add ax, 10
31     loop t
32     mov cx, dx
33     mov es, ax
34     mov di, si
35     add di, si
36     mov al, [si]
37     mov es:[di], al
38     mov es:[di].1, bl
39     inc si
40     loop s
41     ret
42 code ends
43 end start

运行结果:

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

 

 如图,打印了字符。

5. 实验任务5

源码:

assume cs:code, ds:data

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

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

    call printStuNum    ; 调用打印子程序

    mov ah, 4ch
    int 21h

; 打印子程序:
;   参数说明:
;       学号字符串存储在 -> ds:[di]
printStuNum:
    mov ax, 0b800h
    mov es, ax      ; 控制显存区域段指针
    mov si, 1       ; 显存区域列指针

; 先把屏幕前24行背景打印成蓝色
    mov al, 24      ; 前24行
    mov dl, 80      ; 每行80个字符需要修改颜色
    mul dl          ; 24*80, 获得需要填充蓝色的字符数

    mov cx, ax      
    printBlue:
        mov al, 17h         ; 蓝底+白字:0 001 0 111 -> 17h
        mov es:[si], al     ; 把颜色填充到位
        add si, 2           ; 后移2个
    loop printBlue

    sub si, 1        ; 指针回退一个, 从最后一行起始位置开始

; 打印最后一行
    mov ax, 80       
    sub ax, len      ; 80列 - 学号长度
    mov dl, 2        
    div dl           ; (80 - len)/2, 就是学号左右两侧需要填充'-'的长度
    mov dx, ax       ; 使用dx保存'-'的长度
    
    ; 调用打印'-'的子程序, 打印学号左侧的'-'
    mov cx, dx
    call printSeparator 

    ; 打印学号字符串
    mov cx, len
    printNumber:
        mov al, ds:[di]        ; 低位是字符
        mov ah, 17h                ; 高位是颜色
        mov word ptr es:[si], ax    ; 按字放入
        inc di
        add si, 2
    loop printNumber

    ; 再次调用打印'-'的子程序, 打印学号右侧的'-'
    mov cx, dx
    call printSeparator

    ret

; 子程序: 打印分隔符'-'
;   参数: 长度 -> cx
;        位置 -> es:[si]
printSeparator:
    mov al, '-'
    mov ah, 17h
    mov word ptr es:[si], ax
    add si, 2
    loop printSeparator
    ret

code ends
end start

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

实现了效果

 

脚本宝典总结

以上是脚本宝典为你收集整理的实验3 转移指令跳转原理及其简单应用编程全部内容,希望文章能够帮你解决实验3 转移指令跳转原理及其简单应用编程所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: