汇编实验三

四、实验结论

1. 实验任务1

(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 

运行截图:(命名为1.asm)

(2)

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

 跳转的位移量=000D h- 001B h=13-27=-14

从CPU的角度, Loop s1的机器码中,包含转移的位移,CPU执行E2F2时,当前(IP)=001B h,将当前IP值001B h加上-14(-14的补码为F2)即为000D h。

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

 

跳转的位移量=0029 h- 0039 h=41-57=-16

从CPU的角度, Loop s2的机器码中,包含转移的位移,CPU执行E2F0时,当前(IP)=0039 h,将当前IP值0039 h加上-16(-16的补码为F0)即为0029 h。(-16的二进制为1 0001 0000,除符号位外,取反末位加1 得补码F0)

2. 实验任务2

(1)源码:

 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

(2)

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

call word ptr ds:[0]将pop ax的偏移地址压入栈中,pop ax又取出该便宜地址送给ax,所以(ax)=pop ax的偏移地址;
同理,(bx)=pop bx的偏移地址,(cx)=段地址

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

由图中可看出,(ax)=0021 h,(bx)=0026 h ,(cx)=076C h

分析:

 如图所示,(ax)=pop ax的偏移地址;(bx)=pop bx的偏移地址,(cx)=段地址;与分析一致。

 

3. 实验任务3

 

(1)程序代码

 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 cx, len
13     mov si, 0
14 s:   
15     mov ah, 0
16     mov al, [si]         ;每个数
17     call  printNumber
18     call printSpace
19     inc si      ;     下一个数
20     loop s
21 
22     mov ah, 4ch
23     int 21h
24 
25 printNumber:
26     mov bl, 10      ;除数(分离十位数和个位数)
27     div bl
28     mov bx, ax     ;得到的商和余数传给bx
29     mov ah, 2      ;二号子功能
30     mov dl, bl    ;打印商
31      add dl, 30h   ;表示把dl中的商转变成字符,因为‘0’的ASCII码为30H
32      int 21h
33     mov dl, bh     ;打印余数
34     add dl, 30h   
35      int 21h
36      ret
37 
38 printSpace:
39     mov ah, 2       ;二号子功能
40     mov dl, ' '
41     int 21h
42     ret
43 
44 code ends
45 end start

(2)task3.asm 运行截图

 

4. 实验任务4

 

(1)程序代码

 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 bh, 0   ;指定第一行
14     mov bl, 2    ;黑底绿字
15     call printStr
16 
17     mov bh, 24   ;指定最后1行
18     mov bl, 4    ;黑底红字
19     call printStr
20 
21     mov ah, 4ch
22     int 21h
23 
24 printStr:
25    mov al,0ah  ;每行160字节
26    mul bh       ;与行号相乘获得行起始地址
27    add ax, 0b800h
28    mov es,ax 
29 
30     mov cx, len     ;字符串长度
31     mov si, offset str
32     mov di, si
33 s:
34     mov al, [si]   
35     mov ah, bl    ;把颜色属性传入 
36     mov es:[di], ax       ;把要显示的字符送入显存
37     inc si
38     add di, 2
39     loop s
40     ret
41 code ends
42 end start

(2)运行测试截图

 

 

 

5. 实验任务5

 

(1)程序代码

 1 assume cs:code, ds:data
 2 data segment
 3         stu_no db '201983290342'
 4     len = $ - stu_no
 5 data ends
 6 
 7 code segment
 8 start:
 9      mov ax, data
10      mov ds, ax
11       mov ax, 0b800h
12       mov es, ax     ;显存
13       mov si,0    ;存入0里的是字符,存入1的是属性,我的代码两个都写入,所以从0开始
14       mov cx, 1920          ;0-23行(24行*80)(总共25行)
15       mov bh, 17h           ;颜色:蓝底白字
16       mov bl, ' '                ;将0-23行都赋为空
17       
18 s1:
19       mov es:[si], bx
20       add si, 2
21       loop s1                        ;s1循环结束后,s1正好指向24行的第一个字节
22           
23       mov di, si                     ;保存si,以便下面存入学号
24       mov cx, 80
25       mov bl, '-'                     ;存入‘-26 s2:
27      mov es:[si], bx
28      add si, 2
29      loop s2
30 
31       mov cx, len           ;打印学号
32       mov si, di
33       add si, 68        ;最后一行总共80字,0-33,46-79为'-',34开始(34-45)为学号(34*2=6834       mov di, offset stu_no
35 s3:
36       mov bl, [di]
37       mov es:[si], bx
38       add si, 2
39        inc di
40       loop s3
41 
42       mov ah, 4ch
43       int 21h
44 code ends
45 end start

(2)运行测试截图

 

 

 

四、实验结论

(1)实验任务3一开始没有写二号子功能(输出单个字符),程序直接退出;

(2)任务4一开始直接将mov ax, 0b800h      mov es,ax  只能打印出一行信息;

(3)任务5 将学号位置定位为最后一行初始号+34错误,而是+68。

 

posted @ 2021-11-28 10:47  tatazy  阅读(72)  评论(2编辑  收藏  举报