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

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

 编译、连接、运行截图:

 

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

debug反汇编:

(1)loop指令的机器码为E2F2,跳转的8位位移=标号处的地址-loop指令后的第一个字节的地址。

这里标号处的地址是s1的地址为076B:000D,loop指令后的第一个字节的地址是loop后下一条指令的地址为076B:001B。

所以8位位移=000D-001B=-0E(十六进制)=-14(十进制),十六进制补码为F2。

(2)CPU计算跳转后的偏移地址(IP)是通过loop指令的机器码和当前IP得出的。

机器码E2F2,其中E2表明此命令为loop指令,F2为位移量的十六进制补码形式。

当CPU读取并执行E2F2时,当前IP=001B(0019+0003),跳转后IP=当前IP+位移量=001B-0E=000D

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

debug反汇编:

(1)loop指令的机器码为E2F0,跳转的8位位移=标号处的地址-loop指令后的第一个字节的地址。

这里标号处的地址是s2的地址为076B:0029,loop指令后的第一个字节的地址是loop后下一条指令的地址为076B:0039。

所以8位位移=0029-0039=-10(十六进制)=-16(十进制),十六进制补码为F0。

(2)CPU计算跳转后的偏移地址(IP)是通过loop指令的机器码和当前IP得出的。

机器码E2F0,其中E2表明此命令为loop指令,F0为位移量的十六进制补码形式。

当CPU读取并执行E2F0时,当前IP=0039(0037+0002),跳转后IP=当前IP+位移量=0039-10=0029

2. 实验任务2

1)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
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

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

(1)call word ptr 内存单元相当于

  push IP

  jmp word ptr 内存单元地址

(2)call dword ptr 内存单元相当于

  push CS

  push IP

  jmp dword ptr 内存单元地址

(3)ds:[0]中存放的是s1的IP,ds:[2]中存放的是s2的IP。第一个call指令先将s1的IP压入栈,再跳转到ds:[0]即s1处执行pop ax,即将s1的IP=0021出栈并存放到ax。

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

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

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

 编译、连接截图:

使用debug调试,观察、验证调试结果

 

 运行到31行前 -g 076C:0028

 可以看到ax=0021,bx=0026,cx=076C,与理论值一致。

3. 实验任务3

 编写8086汇编源程序task3.asm,在屏幕上以十进制形式输出data段中这一组连续的数据,数据和数据之间以空格间隔。

1)task3.asm源码:

 1 assume cs:code, ds:data
 2 
 3 data segment
 4         x db 99, 72, 85, 63, 89, 97, 55
 5         len equ $ - x
 6 data ends
 7 
 8 code segment
 9 start:
10         mov ax, data
11         mov ds, ax
12         mov si, offset x
13         mov cx, len
14         mov byte ptr ds:[8],10 ;用一个内存单元存储除数10,注意不要用到已经用过的内存空间
15 
16 s:      mov ah, 0
17         mov al, [si]
18         div byte ptr ds:[8] ;被除数x除10的余数和商保存在ax中
19         call printNumber
20         call printSpace
21 
22         inc si
23         loop s
24 
25         mov ax, 4c00h
26         int 21h
27 
28 printNumber:
29         mov bx, ax ;这里用bx暂存,因为输出字符要用到ax
30         or bh, 30h ;转换为数字的ASCII码值
31         or bl,30h
32         mov ah,2 ;准备输出字符
33         mov dl,bl ;先输出商
34         int 21h;
35         mov dl,bh ;再输出余数
36         int 21h;
37         ret
38 
39 printSpace:
40         mov ah, 2
41         mov dl, ' '
42         int 21h
43         ret
44 
45 code ends
46 end start

2)运行测试截图

  4. 实验任务4

在屏幕上以指定颜色、指定行,在屏幕上输出字符串。

1)task4.asm源码:

 1 assume cs:code, ds:data
 2 
 3 data segment
 4         str db 'try'
 5         len equ $ - str
 6 data ends
 7 
 8 code segment
 9 start:   
10         mov ax, data
11         mov ds, ax
12         mov ax, 0b800h ;显示缓冲区开头
13         mov es, ax
14 
15         mov si, offset str
16         mov cx, len
17         mov bl, 2h ;颜色为绿色
18         mov bh, 0 ;行数为第0行
19         call printStr
20 
21         mov si, offset str
22         mov cx, len
23         mov bl, 4h ;颜色为红色
24         mov bh, 24 ;行数为第24行
25         call printStr
26 
27         mov ax, 4c00h
28         int 21h
29 
30 printStr:
31         mov al, 160 ;每一行字符占用空间: 80×2=160Bytes
32         mul bh 
33         mov di, ax ;ax为第bh行的偏移量
34 s:      mov ah, ds:[si]
35         mov es:[di], ah ;字符
36         mov es:[di+1], bl ;颜色
37 
38         add di, 2
39         inc si
40         loop s
41         ret
42         
43 code ends
44 end start

2)运行测试截图

 5.实验任务5

在80×25彩色字符模式下,在屏幕最后一行正中间显示学号。要求输出窗口蓝底,学号和两侧折线,以白色前景色显示。

蓝底白字:0,001,0,111=17h

1)task5.asm源码:

 1 assume ds:data, cs:code
 2 
 3 data segment
 4     stu_no db '201983290278'
 5     len = $ - stu_no
 6 data ends
 7 
 8 code segment
 9 start:
10         mov ax, data
11         mov ds, ax
12         mov ax, 0b800h
13         mov es, ax
14         mov cx, 4000 ;每一屏的内容在显示缓冲区所占字节数:80×25×2 = 4000Bytes
15         mov di, 0
16         mov ah,17h ;蓝底白字
17 
18 s1:    mov al, 0
19         mov es:[di], al
20         mov es:[di+1], ah
21         add di, 2
22         loop s1
23 
24         ;最后一行开始的-
25         mov di, 3840 ;第24行开始
26         mov cx, 34 ;=(160-12*2)/2/2
27         mov ah, 17h
28 s2:    call printSign
29         add di, 2
30         loop s2
31 
32         ;打印学号
33         mov di, 3908 ;3840+(160-12*2)/2=3840+68
34         mov si, offset stu_no
35         mov cx, len
36         mov ah, 17h
37 s3:    call printStu_no
38         inc si
39         add di, 2
40         loop s3
41 
42         ;最后一行最后的-
43         mov di, 3932 ;=3840-68
44         mov cx, 34
45         mov ah, 17h
46 s4:    call printSign
47         add di, 2
48         loop s4
49 
50         mov ax, 4c00h
51         int 21h
52 
53 printStu_no:
54         mov al, [si]
55         mov es:[di], al
56         mov es:[di+1], ah
57         ret
58 
59 printSign:
60         mov al, 2Dh ;-
61         mov es:[di], al
62         mov es:[di + 1], ah
63         ret
64 
65 code ends
66 end start

2)运行测试截图

 

posted @ 2021-11-26 15:32  HypnosTT  阅读(170)  评论(3)    收藏  举报