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

实验任务1

 1 assume cs:code, ds:data
 2 data segment
 3 x db 1, 9, 3
 4 len1 equ $ - x ; 符号常量, $指下一个数据项的偏移地址,这个示例中,是3
 5 y dw 1, 9, 3
 6 len2 equ $ - y ; 符号常量, $指下一个数据项的偏移地址,这个示例中,是9
 7 data ends
 8 code segment
 9 start:
10 mov ax, data
11 mov ds, ax
12 mov si, offset x ; 取符号x对应的偏移地址0 -> si
13 mov cx, len1 ; 从符号x开始的连续字节数据项个数 -> cx
14 mov ah, 2
15 s1:mov dl, [si]
16 or dl, 30h
17 int 21h
18 mov dl, ' '
19 int 21h ; 输出空格
20 inc si
21 loop s1
22 mov ah, 2
23 mov dl, 0ah
24 int 21h ; 换行
25 mov si, offset y ; 取符号y对应的偏移地址3 -> si
26 mov cx, len2/2 ; 从符号y开始的连续字数据项个数 -> cx
27 mov ah, 2
28 s2:mov dx, [si]
29 or dl, 30h
30 int 21h
31 mov dl, ' '
32 int 21h ; 输出空格
33 add si, 2
34 loop s2
35 mov ah, 4ch
36 int 21h
37 code ends
38 end start

tip:理解运算符offset、伪指令equ、预定义符号$的灵活使用。 通过line5、line8,以及数据项的数据属性(字节、字、双字,等),可以方便计算出连续数据项的个数,而无需人工计数。

注*: 符号常量len1, len2不占用数据段内存空间

问题①

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

 跳转的位移量是14,CPU通过loop指令下一条指令的地址减去s1所在地址得到偏移地址。

问题②

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

 位移量是16,CPU通过loop指令下一条指令的地址减去s1所在地址得到偏移地址。

问题③

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

见上述截图。

实验任务2

 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) = ? 寄存器(bx) = ? 寄存器(cx) = ?

 call在跳转之前,会把当前ip或者cs和ip先做入栈操作,然后再跳转。

所以,ax里是pop ax的地址,bx里是px bx的地址,cx里是cs的值。

问题②

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

 

实验任务3

针对8086CPU,已知逻辑段定义如下:

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

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

要求:

编写子程序printNumber

功能:以十进制形式输出一个两位数

入口参数:寄存器ax(待输出的数据 --> ax)

出口参数:无

编写子程序printSpace

功能:打印一个空格

入口参数:无

出口参数:无

在主体代码中,综合应用寻址方式和循环,调用printNumber和printSpace, 实现题目要求。

tip:int 21h中的2号子功能说明如下

; 功能:输出单个字符
mov ah, 2
mov dl, ×× ; ××是待输出的字符,或其ASCⅡ码值
int 21h

 代码如下:

 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,ax13     
12 mov bx,0
13 mov cx,len
14 mov byte ptr ds:[len],10 15 16 s: mov ax,0 17 mov al,ds:[bx] 18 call printNumber 19 call printSpace 20 inc bx 21 loop s 22 23 mov ah,4ch 24 int 21h 25 26 printNumber: 27 div byte ptr ds:[len] 28 mov dx,ax 29 or dl,30h 30 mov ah,2 31 int 21h 32 33 mov dl,dh 34 or dl,30h 35 mov ah,2 36 int 21h 37 38 ret 39 40 printSpace: 41 mov dl,' ' 42 mov ah,2 43 int 21h 44 ret 45 46 code ends 47 end start

实验任务4

针对8086CPU,已知逻辑段定义如下:

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

编写8086汇编源程序task4.asm,在屏幕上以指定颜色、指定行,在屏幕上输出字符串。

要求:

编写子程序printStr

功能:在指定行、以指定颜色,在屏幕上显示字符串

入口参数 字符串首字符地址 --> ds:si(其中,字符串所在段的段地址—> ds, 字符串起始地址的偏 移地址—> si) 字符串长度 --> cx 字符串颜色 --> bl 指定行 --> bh (取值:0 ~24)

出口参数:无 

在主体代码中,两次调用printStr,使得在屏幕最上方以黑底绿字显示字符串,在屏幕最下方以黑底红色显示字符串

代码如下:

 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 
13     mov si,0
14     mov cx,len
15     mov bl,00000010b
16     mov bh,0
17     call printStr
18 
19     mov si,0
20     mov cx,len
21     mov bl,00000100b
22     mov bh,24
23     call printStr
24 
25     mov ah,4ch
26     int 21h
27 
28 printStr:
29     mov ax,0b800h
30     mov es,ax
31     mov ax,0
32     mov al,bh
33     mov dx,160
34     mul dx
35     mov di,ax
36     s:    mov al,ds:[si]
37         mov es:[di],al
38         inc si
39         inc di
40         mov es:[di],bl
41         inc di
42         loop s
43     ret
44 code ends
45 end start

实验任务5

针对8086CPU,针对8086CPU,已知逻辑段定义如下:

1 data segment
2 stu_no db '20498329042'
3 len = $ - stu_no
4 data ends

在80×25彩色字符模式下,在屏幕最后一行正中间显示学号。

要求输出窗口蓝底,学号和两侧折线,以 白色前景色显示。

tips:

1. 80×25彩色字符模式显示缓冲区结构,参见教材「实验9 根据材料编程」里的说明。

2. 编写程序实现时,将data段的学号换成自己的学号。

代码如下:

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

 
posted @ 2021-12-03 08:51  悬尘往  阅读(86)  评论(3编辑  收藏  举报