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

实验结论

1、实验任务1

task3-1.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

运行的截图:

 回答问题:

  1、line27, 汇编指令 loop s1 跳转时,是根据位移量跳转的。通过debug反汇编,查看其机 器码,分析其跳转的位移量是多少?(位移量数值以十进制数值回答)从CPU的角度,说明 是如何计算得到跳转后标号s1其后指令的偏移地址的。

     当前IP指向下一条指令开始地址,为001B,十进制表示:27

    根据公式:27 + (-14) = 13

    13的十六进制表示为:D,跳转地址即000D

  2、line44,汇编指令 loop s2 跳转时,是根据位移量跳转的。通过debug反汇编,查看其机 器码,分析其跳转的位移量是多少?(位移量数值以十进制数值回答)从CPU的角度,说明 是如何计算得到跳转后标号s2其后指令的偏移地址的。

     当前IP0039,十进制表示:57

    根据公式:57 + (-16) = 41

    41的十六进制表示为:29,跳转地址即0029。

  3、附上上述分析时,在debug中进行调试观察的反汇编截图。

 

 

 2、实验任务2

task3-2.asm源码:

 1 assume cs:code, ds:data
 2 
 3 data segment
 4     dw 200h, 0h, 230h, 0h
 5 data ends
 6 
 7 stack segment
 8     db 16 dup(0)
 9 stack ends
10 
11 code segment
12 start:  
13     mov ax, data
14     mov ds, ax
15 
16     mov word ptr ds:[0], offset s1
17     mov word ptr ds:[2], offset s2
18     mov ds:[4], cs
19 
20     mov ax, stack
21     mov ss, ax
22     mov sp, 16
23 
24     call word ptr ds:[0]
25 s1: pop ax
26 
27     call dword ptr ds:[2]
28 s2: pop bx
29     pop cx
30 
31     mov ah, 4ch
32     int 21h
33 code ends
34 end start

回答问题:

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

     ax=0021h,bx=0026h,cx=076Ch 。

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

    对源程序进行汇编、链接并使用debug调试后得到的结果截图如下,与分析结果一致。

 

3、实验任务3

task3-3.asm源码: 

 1 assume ds:data, cs:code, ss:stack
 2 
 3 data segment
 4     x db 99, 72, 85, 63, 89, 97, 55
 5     len equ $ - x
 6 data ends
 7 
 8 stack segment
 9     dw 16 dup(?)
10 stack ends
11 
12 code segment
13 start:
14     mov ax, data
15     mov ds, ax
16 
17     mov ax, stack
18     mov ss, ax
19     mov sp, 32
20 
21     mov cx, len ; 由于数据都是byte型,所以len就是数据个数
22     ; print循环: 依次打印所有数字
23     print:
24         mov ah, 0                   ; 数据只有一个字节,先把ah置0,子函数中除法是以ax作为被除数的
25         mov al, byte ptr ds:[di]    ; 把数据放入al
26         inc di                      ; di指针后移
27 
28         push cx             ; 把cx保存起来, 子程序中会修改cx值
29 
30         call printNumber    ; 打印数字
31         call printSpace     ; 打印空格
32 
33         pop cx              ; 恢复cx
34     loop print
35     
36     mov ah, 4ch
37     int 21h
38 
39 ; 子程序: printNumber
40 ; 功能: 打印数字
41 ;   入口参数: 
42 ;       寄存器ax  (待输出的数据 --> ax)
43 ;   局部变量说明: 
44 ;       bx -> 存储数字字符个数
45 printNumber:
46     mov bx, 0       ; 获取之前位数为0
47     ; 逐位获取数字
48     ; getEach循环: 获取每一位,然后压入栈中
49     getEach:
50         mov dl, 10      
51         div dl          ; 数据除10
52 
53         push ax         ; 将数字压入栈中(ah余数在ax里了)
54         inc bx          ; 位数+1
55         
56         mov ah, 0       ; ah是余数,置0后ax表示除法的结果
57         mov cx, ax      ; 除法结果赋给cx, 如果结果为0则说明所有位数都获取完了
58         inc cx          ; 由于loop时会-1,这里先+1,防止出现负数
59 
60     loop getEach
61 
62     ; 打印数字
63     mov cx, bx          ; 先把bx存的数字位数赋给cx
64     ; printEach循环: 依次从栈中取出数字,逐位打印
65     printEach:
66         pop ax          ; 取出一位数
67         add ah, 30h     ; ah是刚才除法的余数,也就是需要得到的位数,+30h是转成对应字符
68         mov dl, ah      ; 放到dl, 用于打印
69         mov ah, 2       ; 调用int 21h的2号子程序打印
70         int 21h
71     loop printEach 
72 
73     ret
74 
75 ; 子程序: printSpace
76 ; 功能: 打印空格
77 printSpace:
78     mov ah, 2
79     mov dl, 20h
80     int 21h
81     ret
82 
83 code ends
84 end start

运行结果截图:

 

4、实验任务4

task3-4.asm源码:

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

运行结果截图:

 

5、实验任务5

task3-5.asm源码:

 1 assume cs:code, ds:data
 2 
 3 data segment
 4     stu_no db '201983290239'
 5     len = $ - stu_no
 6 data ends
 7 
 8 code segment
 9 start:
10     mov ax, data
11     mov ds, ax
12     mov di, 0
13 
14     call printStuNum    ; 调用打印子程序
15 
16     mov ah, 4ch
17     int 21h
18 
19 ; 打印子程序:
20 ;   参数说明:
21 ;       学号字符串存储在 -> ds:[di]
22 printStuNum:
23     mov ax, 0b800h
24     mov es, ax      ; 控制显存区域段指针
25     mov si, 1       ; 显存区域列指针
26 
27 ; 先把屏幕前24行背景打印成蓝色
28     mov al, 24      ; 前24行
29     mov dl, 80      ; 每行80个字符需要修改颜色
30     mul dl          ; 24*80, 获得需要填充蓝色的字符数
31 
32     mov cx, ax      
33     printBlue:
34         mov al, 17h         ; 蓝底+白字:0 001 0 111 -> 17h
35         mov es:[si], al     ; 把颜色填充到位
36         add si, 2           ; 后移2个
37     loop printBlue
38 
39     sub si, 1        ; 指针回退一个, 从最后一行起始位置开始
40 
41 ; 打印最后一行
42     mov ax, 80       
43     sub ax, len      ; 80列 - 学号长度
44     mov dl, 2        
45     div dl           ; (80 - len)/2, 就是学号左右两侧需要填充'-'的长度
46     mov dx, ax       ; 使用dx保存'-'的长度
47     
48     ; 调用打印'-'的子程序, 打印学号左侧的'-'
49     mov cx, dx
50     call printSeparator 
51 
52     ; 打印学号字符串
53     mov cx, len
54     printNumber:
55         mov al, ds:[di]        ; 低位是字符
56         mov ah, 17h                ; 高位是颜色
57         mov word ptr es:[si], ax    ; 按字放入
58         inc di
59         add si, 2
60     loop printNumber
61 
62     ; 再次调用打印'-'的子程序, 打印学号右侧的'-'
63     mov cx, dx
64     call printSeparator
65 
66     ret
67 
68 ; 子程序: 打印分隔符'-'
69 ;   参数: 长度 -> cx
70 ;        位置 -> es:[si]
71 printSeparator:
72     mov al, '-'
73     mov ah, 17h
74     mov word ptr es:[si], ax
75     add si, 2
76     loop printSeparator
77     ret
78 
79 code ends
80 end start

运行结果截图:

 

posted @ 2021-11-29 14:08  吹吹哭哭惹  阅读(121)  评论(3编辑  收藏  举报