实验2 多个逻辑段的汇编源程序编写与调试

实验结论

1、实验任务1

任务1-1

task1_1.asm源码:

 1 assume ds:data, cs:code, ss:stack
 2 data segment
 3     db 16 dup(0) ; 预留16个字节单元,初始值均为0
 4 data ends
 5 stack segment
 6     db 16 dup(0) ; 预留16个字节单元,初始值均为0
 7 stack ends
 8 code segment
 9 start:
10     mov ax, data
11     mov ds, ax
12     mov ax, stack
13     mov ss, ax
14     mov sp, 16 ; 设置栈顶
15 mov ah, 4ch
16     int 21h
17 code ends
18 end start

task1_1调试到line17结束、line19之前截图

问题回答

1)在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) = _076A_, 寄存器(SS) = _076B_, 寄存器(CS) = _076C__

2)假设程序加载后,code段的段地址是X,则,data段的段地址是_ X-2h__, stack的段地址是 _ X-1h__

 

任务1-2

task1_2.asm源码:

 1 assume ds:data, cs:code, ss:stack
 2 data segment
 3     db 4 dup(0) ; 预留4个字节单元,初始值均为0
 4 data ends
 5 stack segment
 6     db 8 dup(0) ; 预留8个字节单元,初始值均为0
 7 stack ends
 8 code segment
 9 start:
10     mov ax, data
11     mov ds, ax
12     mov ax, stack
13     mov ss, ax
14     mov sp, 8   ; 设置栈顶
15 mov ah, 4ch
16     int 21h
17 code ends
18 end start

task1_2调试到line17结束、line19之前截图

问题回答

1)在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) = _076A_, 寄存器(SS) = _076B_, 寄存器(CS) = _076C__

2)假设程序加载后,code段的段地址是X,则,data段的段地址是_ X-2h__, stack的段地址是 _ X-1h__

 

任务1-3

task1_3.asm源码:

assume ds:data, cs:code, ss:stack
 2 data segment
 3     db 20 dup(0) ; 预留20个字节单元,初始值均为0
 4 data ends
 5 stack segment
 6     db 20 dup(0) ; 预留20个字节单元,初始值均为0
 7 stack ends
 8 code segment
 9 start:
10     mov ax, data
11     mov ds, ax
12     mov ax, stack
13     mov ss, ax
14     mov sp, 20 ; 设置栈顶
15 mov ah, 4ch
16     int 21h
17 code ends
18 end start

task1_3调试到line17结束、line19之前截图

问题回答

1)在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) = _076A_, 寄存器(SS) = _076C_, 寄存器(CS) = _076E__

2)假设程序加载后,code段的段地址是X,则,data段的段地址是_ X-4h__, stack的段地址是 _ X-2h__

 

任务1-4

task1_4.asm源码:

 1 assume ds:data, cs:code, ss:stack
 2 code segment
 3 start:
 4     mov ax, data
 5     mov ds, ax
 6     mov ax, stack
 7     mov ss, ax
 8     mov sp, 20
 9 mov ah, 4ch
10     int 21h
11 code ends
12 data segment
13     db 20 dup(0)
14 data ends
15 stack segment
16     db 20 dup(0)
17 stack ends
18 end start

task1_4调试到line9结束、line11之前观察寄存器DS, CS, SS值的截图

问题回答

1)在debug中将执行到line9结束、line11之前,记录此时:寄存器(DS) = _076C_, 寄存器(SS) = _076E_, 寄存器(CS) = _076A__

2)假设程序加载后,code段的段地址是X,则,data段的段地址是_ X+2h__, stack的段地址是 _ X+4h__

 

任务1-5

1)对于如下定义的段,程序加载后,实际分配给该段的内存空间大小是 _ [ N / 16 ] * 16  ([ ]为向上取整)___。

1 xxx segment
2     db N dup(0)
3 xxx ends

2)如果将程序task1_1.asm, task1_2.asm, task1_3.asm, task1_4.asm中,伪指令 end start 改成 end , 哪一个程序仍然可以正确执行。结合实践观察得到的结论,分析、说明原因。

task1_4.asm仍然可以运行。

 

2、实验任务2

汇编源代码:

code segment
start:
    mov ax, 0b800h
    mov ds, ax
    mov bx, 0f00h
    mov cx, 50h  ; 160字节需写入80次,对应16进制数50h
    mov ax, 0403h ; 低位03 高位04
s:  mov ds:[bx], ax
    add bx, 2
    loop s

    mov ah, 4ch
    int 21h
code ends
end start

运行结果: 

 

 

3、实验任务3

补充完整的汇编源码:

 1 assume ds:data1, cs:code 
 2 data1 segment
 3     db 50, 48, 50, 50, 0, 48, 49, 0, 48, 49 ; ten numbers
 4 data1 ends
 5 
 6 data2 segment
 7     db 0, 0, 0, 0, 47, 0, 0, 47, 0, 0       ; ten numbers
 8 data2 ends
 9 
10 data3 segment
11     db 16 dup(0)
12 data3 ends
13 
14 code segment
15 start:
16     mov ax, data1
17     mov ds, ax
18     mov bx, 0
19     mov cx, 0ah       ; 循环10次,对应16进制数0ah
20 s:  mov ax, ds:[bx]
21     add ax, ds:[bx+10h]    ; 将data2中对应数据加到ax 地址相差16字节,即10h
22     mov ds:[bx+20h], ax    ; 把ax数据存入data3对应位置 地址相差32字节,即20h
23     inc bx
24     loop s
25 
26    mov ah, 4ch
27    int 21h
28 code ends
29 end start

反汇编

在数据项依次相加之前,查看逻辑段data1, data2, data3对应的内存空间数据原始值的 debug命令

使用g 8 命令调试到循环执行前,再使用d ds:0命令查看内存空间数据原始值

使用g 16命令调试到循环执行结束,再使用d ds:0命令查看相加后内存空间数据

可见实现了把逻辑段data1和逻辑段data2的数据依次相加,结果保存到逻辑段data3中的要求。

 

4、实验任务4

补充完整的汇编源码:

 1 assume cs:code
 2 
 3 data1 segment
 4     dw 2, 0, 4, 9, 2, 0, 1, 9
 5 data1 ends 
 6 
 7 data2 segment
 8     dw 8 dup(?)
 9 data2 ends
10 
11 ;定义栈段stack
12 stack segment
13     dw 8 dup(0)
14 stack ends
15 
16 code segment
17 start:
18     ; 将data1数据入栈
19     mov ax, data1
20     mov ds, ax
21     mov sp, 9  ; 设置栈顶为9
22     mov bx, 0
23     mov cx, 8   ; 共8个元素,循环8次
24 s1: push ds:[bx]
25     add bx, 2
26     loop s1
27 
28     ; 将栈内数据出栈到data2
29     mov ax, data2
30     mov ds, ax
31     mov bx, 0
32     mov cx, 8
33 s2: pop ds:[bx]
34     add bx, 2
35     loop s2
36 
37     mov ah, 4ch
38     int 21h
39 code ends
40 end start

执行前数据段data1、data2内数据

执行后数据段data2内数据(即地址076A:0010开始)

可见正确实现了把逻辑段data1中的8个字数据逆序存储到逻辑段b中的要求。

 

5、实验任务5

task5.asm源码:

 1 assume cs:code, ds:data
 2 data segment
 3         db 'Nuist'
 4         db 2, 3, 4, 5, 6
 5 data ends
 6 
 7 code segment
 8 start:
 9         mov ax, data
10         mov ds, ax
11 
12         mov ax, 0b800H
13         mov es, ax
14 
15         mov cx, 5
16         mov si, 0
17         mov di, 0f00h
18 s:      mov al, [si]
19         and al, 0dfh
20         mov es:[di], al
21         mov al, [5+si]
22         mov es:[di+1], al
23         inc si
24         add di, 2
25         loop s
26 
27         mov ah, 4ch
28         int 21h
29 code ends
30 end start

运行结果截图:

使用debug工具对程序进行调试,使用g命令一次性执行到程序返回前截图:

源代码中line19的作用:

将小写字母转换为大写字母。

修改line4里5个字节单元的值(将值全部改为2),重新汇编、链接、运行,运行结果:

可见字符串颜色改变,因此猜测这里的数值作用为控制输出字符的显示颜色。 

 

6、实验任务6

补全后的task6.asm源码:

 1 assume cs:code, ds:data
 2 
 3 data segment
 4     db 'Pink Floyd      '
 5     db 'JOAN Baez       '
 6     db 'NEIL Young      '
 7     db 'Joan Lennon     '
 8 data ends
 9 
10 code segment
11 start:
12     mov ax, data
13     mov ds, ax
14 
15     mov ax, data
16     mov es, ax
17 
18     mov bx, 0
19     mov cx, 4 ; 外层4个表达式,循环4次
20 
21 s0: mov si, cx
22     mov cx, 4 ; 内层转换第一个单词(4字符),循环4次
23 
24 s1: mov al, es:[bx]
25     or al, 20h  ; 大写->小写 or 00100000B 即or 20h
26     mov es:[bx], al;
27     inc bx
28     loop s1
29 
30     mov cx, si
31     mov bx, 0
32     mov ax, es
33     inc ax
34     mov es, ax
35     loop s0
36     
37     mov ah, 4ch
38     int 21h
39 code ends
40 end start

在程序退出前,使用d命令查看数据段data对应的内存空间的截图:

在debug中使用反汇编命令u观察到退出语句地址为076A:002C

使用g 002C命令后使用d ds:0命令查看数据段data对应内存空间数据

可见正确实现了将data段中的每行第一个单词从大写->小写。

 

7、实验任务7

补全的task7.asm源码:

 1 assume cs:code, ds:data, es:table
 2 
 3 data segment
 4     db '1975', '1976', '1977', '1978', '1979'  ; 起始地址0 每次偏移量4
 5     dw  16, 22, 382, 1356, 2390 ; 起始地址20 每次偏移量2
 6     dw  3, 7, 9, 13, 28  ; 起始地址30 每次偏移量2
 7 data ends
 8 
 9 table segment
10     db 5 dup( 16 dup(' ') )  ;
11 table ends
12 
13 code segment
14 start:
15     mov ax, data
16     mov ds, ax
17     mov ax, table
18     mov es, ax
19 
20     mov cx, 5
21     mov bx, 0
22     mov si, 0
23     mov di, 0
24 s:
25     mov ax, [bx+2]
26     mov es:[di+2], ax
27     mov ax, [bx]
28     mov es:[di], ax
29     mov ax, [si+20]
30     mov word ptr es:[di+5], 0
31     mov word ptr es:[di+7], ax
32     mov ax, [si+30]
33     mov word ptr es:[di+11], ax
34     mov word ptr es:[di+9], 0
35     mov ax, es:[di+7]
36     div byte ptr es:[di+11]
37     mov byte ptr es:[di+13], 0
38     mov es:[di+14], al
39     add bx, 4
40     add si, 2
41     add di, 16
42     loop s
43     
44     mov ah, 4ch
45     int 21h
46 code ends
47 end start

在debug中利用u命令反汇编,并利用g命令调试到循环开始前,再利用d命令查看ds, es内原始数据

再次利用g命令调试到程序退出前,利用d命令查看es内数据

可见数据按要求存放在了表格中。

 

实验总结

1、将字符由大写转换为小写时,可以使用and 0DFH实现,大写转小写可以使用or 20H实现。

2、使用双层循环结构时,需要在内循环开始前保存外循环循环次数(即寄存器cx的值),内循环结束后恢复cx的值。

3、段内定义内存空间N,则程序加载后实际分配给段的内存空间大小是  [ N / 16 ] * 16  ([ ]为向上取整)。

posted on 2021-11-07 14:37  赤望  阅读(74)  评论(2)    收藏  举报

导航