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

一、实验目的

  1. 理解和掌握转移指令的跳转原理

  2. 掌握使用call和ret指令实现子程序的方法,理解和掌握其参数传递方式

  3. 理解和掌握80×25彩色字符模式显示原理

  4. 综合应用寻址方式和汇编指令完成简单应用编程

二、实验准备

  复习教材9-10章: 转移指令的跳转原理 汇编指令jmp, loop, jcxz, call, ret, retf的用法

三、实验内容

 实验任务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

 

  问题1:程序反汇编截图如下:

  

 

 

   可以看到Loop处的机器码为E2F2,这里E2为Loop,而F2的含义是偏移量的补码形式,我们将F2的2进制(11110010)求补后得10001110,即10进制中的-14,代表向前偏移14个字节,而我们用Loop指令的偏移地址与s1的偏移地址相减时发现偏移量为-12,所以并非从Loop指令处计算,而是从它的下一个指令所在的偏移地址计算,在本题中是001B,用001B和000D相减,可以得到偏移量为-14。CPU应该是先取Loop指令的下一条指令的偏移地址,然后从Loop指令的机器码后两位中获得偏移量的补码形式,再求补得到偏移量,然后用下一条指令的偏移地址与偏移量相减得到跳转位置的偏移地址000D。

  问题2:程序反汇编截图如下:

  

 

 

   可以看到Loop处的机器码为E2F0,同问题1,由F0(11110000)求补得到10010000,即十进制中的-16,代表向前偏移16个字节,而此时CPU也是从Loop指令的下一条指令的偏移地址0039开始计算,将它与16相减,获得s2处的偏移地址0029。

  实验任务2:

  task2.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:从理论上看:

  (1)call word ptr将下一条指令的偏移地址压入栈,再跳转到相应地址执行命令

       (2)call dword ptr 先将下一条指令的段地址压入栈,再将下一条指令的偏移地址压入栈,再跳转到相应地址执行命令。

       (3)本题ds:[0]中存放的是s1的偏移地址,ds:[2]中存放的是s2的偏移地址,所以第一个call指令先将s1的偏移地址压入栈,在跳转到s1处执行pop ax,即将s1的偏移地址0021出栈并存放到ax。

       (4)第二个call指令先将s2处的偏移地址压入栈,再将s2处的段地址压入栈,再跳转到ds:[2]即s2处执行pop bx,即将s2的偏移地址0026出栈并存放到bx,再执行pop cx,即将s2的段地址076C出栈并存放到cx中。

  综上可得程序执行到line31之前,ax=0021,bx=0026,cx=076C

  问题2:在debug中验证,反汇编截图如下:

  

  

  执行到line31之前:

  

  可以看到ax=0021,bx=0026,cx=076C,验证正确。

  实验任务3:

  task3.asm代码编写如下:

 1 assume ds:data, cs:code
 2 data segment
 3     x db 99, 72, 85, 63, 89, 97, 55
 4     len equ $- x
 5 data ends
 6 
 7 code segment
 8 start:
 9     mov ax, data
10     mov ds, ax
11     mov si, offset x
12     mov cx, len
13     mov byte ptr ds:[10], 10
14     
15 s1:    mov ah, 0
16     mov al, ds:[si]
17 
18     div byte ptr ds:[10]
19     call printNumber
20     call printSpace
21     inc si
22     loop s1
23 
24     mov ax, 4c00h
25     int 21h
26 
27 printNumber:mov bx, ax
28     or bl, 30h
29     or bh, 30h
30     mov ah, 2
31     mov dl, bl
32     int 21h
33     mov dl, bh
34     int 21h
35     ret
36 
37 printSpace:mov ah, 2
38     mov dl, ' '
39     int 21h
40     ret
41     
42 code ends
43 end start

  在debug中调试截图如下:

  

  实验任务4:

  task4.asm代码编写如下:

 1 assume ds:data, cs:code
 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     mov cx, len
12     mov si, offset str
13     mov ax, 0b800h
14     mov es, ax
15     mov di, 0
16     mov ah, 2
17 
18 s:    call printStr
19     inc si
20     add di, 2
21     loop s
22     
23     mov di, 3840
24     mov si, offset str
25     mov cx, len
26     mov ah, 4
27 
28 s1:    call printStr
29     inc si
30     add di, 2
31     loop s1
32     
33     mov ax, 4c00h
34     int 21h
35 
36 printStr:mov al, [si]
37     mov es:[di], al
38     mov es:[di+1], ah
39     ret
40     
41 code ends
42 end start

  在debug中运行截图如下:

  

  实验任务5:

  task5.asm代码如下:

 1 assume ds:data, cs:code
 2 data segment
 3     stu_no db '201983290205'
 4     len = $ - stu_no
 5 data ends
 6 
 7 code segment
 8 start:
 9     mov ax, data
10     mov ds, ax
11     mov cx, 4000
12     mov si, offset stu_no
13     mov ax, 0b800h
14     mov es, ax
15     mov di, 0
16     mov ah,17h
17 
18 s:    mov al, 0
19     mov es:[di], al
20     mov es:[di+1], ah
21     inc si
22     add di, 2
23     loop s
24     
25     mov di, 3840
26     mov si, offset stu_no
27     mov cx, 74
28     mov ah, 17h
29 s1:    call printgang
30     add di, 2    
31     loop s1
32 
33     mov di, 3908
34     mov si, offset stu_no
35     mov cx, len
36     mov ah, 17h
37 s2:    call printStu_no
38     inc si
39     add di, 2
40     loop s2
41     
42     mov di, 3932
43     mov si, offset stu_no
44     mov cx, 74
45     mov ah, 17h
46 s3:    call printgang
47     add di, 2
48     loop s3
49 
50     mov ax, 4c00h
51     int 21h
52 
53 printStu_no:mov al, [si]
54     mov es:[di], al
55     mov es:[di+1], ah
56     ret
57 
58 printgang:mov al, 45
59     mov es:[di], al
60     mov es:[di + 1], ah
61     ret
62     
63 code ends
64 end start

  在debug中运行截图如下:

 

  四.实验总结

  经过本次上机实验,我学习并理解了转移指令的跳转原理,了解了Loop指令的机器码的含义以及如何计算跳转地址,学会了如何使用call和ret编写子程序并运用,学习了彩色字符是如何打印在屏幕上的,以及它们的属性字节中8个数字分别代表的含义,希望在以后能更深入地学习这方面。

 

 

 

 

posted @ 2021-11-23 21:31  蛋白大神  阅读(177)  评论(3编辑  收藏  举报