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

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

一、实验目的

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

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

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

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

二、实验准备

  复习教材9-10章:

  • 转移指令的跳转原理

  • 汇编指令jmp, loop, jcxz, call, ret, retf的用法

三、实验内容

1. 实验任务1

使用任何一款文本编辑器,录入8086汇编程序源码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

测试运行:

 

 

显示结果输出2行 “1 9 3”

debug查看:

 

 

 

回答问题

① line27,汇编指令 loop s1 跳转时,是根据位移量跳转的。通过 debug 反汇编,查看其机器码,从 CPU 的角度,分析其跳转的位移量,F2即补码11110010,原码10001110,以十进制数值为(-14),推算开始地址为27 + (-14) = 13 -> 000D(十六进制)

② line44,汇编指令 loop s2 跳转时,是根据位移量跳转的。通过 debug 反汇编,查看其机器码,从 CPU 的角度,分析其跳转的位移量,F0即补码11110000,原码10010000,以十进制数值为(16),推算开始地址为57 - 16 = 41 -> 29(十六进制)

 

2. 实验任务2

使用任何一款文本编辑器,录入8086汇编程序源码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

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

② 对源程序进行汇编、链接,得到可执行程序task2.exe。使用debug调试,观察、验证调试结果:ax中存放着s1代码段的地址中的段内偏移地址部分——0021,bx中存放着s2代码段的地址中的段内偏移地址部分——0026,cx中存放着s2代码段的地址中的段地址部分——076C。

 

3. 实验任务3

编写8086汇编源程序task3.asm,在屏幕上以十进制形式输出data段中这一组连续的数据,数据和数据之间以空格间隔。要求:编写两个子程序printNumber、printSpace,分别用来输出两位数和空格。

在主体代码中,综合应用寻址方式和循环,调用printNumber和printSpace,实现题目要求。已知逻辑段定义如下:

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

 设计代码,思路在代码中注释:

 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     
13     mov cx,len
14     mov si,0
15 s1:  mov ah,0
16     mov al,[si]
17     mov bx,offset printnumber
18     call bx
19     mov bx,offset printSpace
20     call bx
21     inc si
22     loop s1
23      
24     mov ah, 4ch
25      int 21h
26 
27 printnumber:
28     mov bl,10 ;以十进制计算个位十位
29     div bl
30     
31     mov bx,ax
32     mov ah,2
33     
34     mov dl,bl ;打印十位数
35     or dl,30h ;转为ASCII值 
36     int 21h
37     
38     mov dl,bh ;打印个位数
39     or dl,30h ;转为ASCII值
40     int 21h
41     
42     ret
43 printSpace:
44     mov ah,2
45     mov dl,' ' ;移入空格打印输出
46     int 21h
47     ret
48 code ends
49 end start

测试结果:正确输出空格间隔的数字,nice

  

4. 实验任务4

编写8086汇编源程序task4.asm,在屏幕上以指定颜色、指定行,在屏幕上输出字符串。
要求编写子程序printStr,实现功能:在指定行、以指定颜色,在屏幕上显示字符串;在主体代码中,两次调用printStr,使得在屏幕最上方以黑底绿字显示字符串,最下方以黑底红字显示字符串。

其中已知逻辑段定义如下:

1 data segment
2       str db 'try'
3       len equ $ - str
4 data ends

 设计代码:思路在代码中注释:

 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 printTry ;第一个try
16     mov ah,00000010B ;黑底绿字为00000010B
17     mov bx,0 ;定位第一行
18     call si
19     
20     mov si,offset printTry ;第二个try
21     mov ah,00000100B ;黑底红字为00000100B
22     mov bx,0F00H ;定位最后一行
23     call si
24     
25     mov ah, 4ch
26      int 21h
27 
28 printTry:
29     mov cx,len
30     mov si,0
31 s1:  mov al,[si]
32     mov es:[bx+si],ax
33     inc si
34     inc bx
35     loop s1
36     ret
37 
38 code ends
39 end start

测试结果:

黑底绿字在这里:

 ↑

黑底红字在这里

5. 实验任务5

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

已知逻辑段定义如下:

1 data segment
2       stu_no db '201983290253' ;自己的学号
3       len = $ - stu_no
4 data ends

设计代码如下: 

 1 assume cs:code, ds:data
 2 
 3 data segment
 4     stu_no db '201983290253' 
 5     len = $ - stu_no
 6 data ends
 7 
 8 code segment
 9 start:  
10      mov ax, data
11      mov ds, ax  ; 数据从ds中来
12     mov ax,0B800H ;显示区缓存地址开始位置
13     mov es,ax    ;数据到es中去,es寄存器指向显存段
14 
15     mov cx,0780H  ;染蓝色
16     mov ah,10H
17     mov al,' '
18     mov bx,0
19 s1:  mov es:[bx],ax
20     add bx,2
21     loop s1
22     
23     mov cx,80;打印横线
24     mov ah,17H ;(00010111)蓝底白字
25     mov al,'-'
26 s2:  mov es:[bx],ax
27     add bx,2
28     loop s2
29 
30     mov cx,len
31     mov bx,0F44H ;居中输出学号
32     mov si,0
33 s3:  mov al,[si]
34     mov es:[bx],ax
35     inc si
36     add bx,2
37     loop s3
38 
39     mov ah, 4ch
40      int 21h
41 
42 code ends
43 end start

展示学号:

 

posted @ 2021-12-03 01:03  IMeanGabriel  阅读(112)  评论(3编辑  收藏  举报