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

实验任务1

  • 任务1-1

  task1_1.asm的源码如下:

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

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

     

 

   问题回答:

  ①在debug中将执行到line17结束、line19之前,此时:寄存器(DS) = 076A, 寄存器(SS) = 076B, 寄存器(CS) = 076C

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

 

  • 任务1-2

  task1_2.asm的源码如下:

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

  task1_2调试到line17结束、line19之前观察寄存器DS, CS, SS值的截图如下:

      

  问题回答:

    ① 在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) = 076A, 寄存器(SS) = 076B, 寄存器(CS) = 076C

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

 

  • 任务1-3

  task1_3.asm的源码如下:

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

  task1_3调试到line17结束、line19之前观察寄存器DS, CS, SS值的截图如下:

    

 

     问题回答:

  ① 在debug中将执行到line17结束、line19之前,记录此时:寄存器(DS) = 076A, 寄存器(SS) = 076C, 寄存器(CS) = 076E

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

 

  • 任务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 
 7     mov ax, stack
 8     mov ss, ax
 9     mov sp, 20
10 
11     mov ah, 4ch
12     int 21h
13 code ends
14 
15 data segment
16     db 20 dup(0)
17 data ends
18 
19 stack segment
20     db 20 dup(0)
21 stack ends
22 end start

  task1_4调试到line17结束、line19之前观察寄存器DS, CS, SS值的截图的截图如下:

       

 

   问题回答:

   ①在debug中将执行到line9结束、line11之前,记录此时:寄存器(DS) = 076C, 寄存器(SS) = 076E, 寄存器(CS) = 076A

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

 

  • 任务1-5

  基于上述四个实验任务的实践、观察,总结并回答:

  ①对于如下定义的段,程序加载后,实际分配给该段的内存空间大小是 16 · ceil(N/16)。(ceil(x)表示对x向上取整)

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

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

     答:将task1_1.asm的伪指令end start 改成 end,编译,链接后,在debug中查看到的汇编代码的截图如下:

             

 

      显然,这个程序在修改伪指令后是不能正确执行的。

      将task1_2.asm的伪指令end start 改成 end,编译,链接后,在debug中查看到的汇编代码的截图如下:

       

 

      和task1_1.asm修改伪指令的情形类似,该程序不能正确执行

      将task1_3.asm的伪指令end start 改成 end,编译,链接后,在debug中查看到的汇编代码的截图如下:

       

 

     可见,该程序在修改伪指令后不能正确执行

     将task1_4.asm的伪指令end start 改成 end,编译,链接后,在debug中查看到的汇编代码的截图如下:

     

 

     此时,修改伪指令后的程序可以正确执行

   出现上面这些现象的原因是:伪指令 end 描述程序的结束和程序的入口,start正是用于指示程序段入口信息的,修改伪指令后,操作系统无法确定程序的入口地址,只能将CS:IP一律设置成076A:0000。对于task1_1.asm, task1_2.asm, task1_3.asm而言,076A:0000处存储的是数据而不是程序,而task1_4.asm在076A:0000恰好是程序段的入口,故能正确执行。

 

实验任务2

  实现的源码如下:

 1 assume cs:code
 2 code segment
 3 start:
 4     mov ax, 0b800H
 5     mov ds, ax
 6     mov bx, 0f00H
 7     mov ax, 0304H
 8     mov cx, 80
 9 s:  mov [bx], ax
10     add bx, 2
11     loop s
12 
13     mov ax, 4c00H
14     int 21H
15 code ends
16 end start

  运行结果截图如下:

    

 

 

实验任务3

  补充完整后的汇编源代码如下:

 1 assume 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 stack1 segment
15      db 16 dup(0)
16 stack1 ends
17 
18 code segment
19 start:
20     mov ax, data1
21     mov ds, ax
22 
23     mov ax, data2
24     mov es, ax
25 
26     mov ax, stack1
27     mov ss, ax
28     mov sp, 16
29 
30     mov bx, 0
31     mov cx, 5   
32 s1: mov ax, ds:[bx]
33     add ax, es:[bx]
34     push ax
35     add bx, 2
36     loop s1
37 
38     mov ax, data3
39     mov ds, ax
40     mov bx, 8
41     mov cx, 5
42 s2: pop ds:[bx]
43     sub bx, 2
44     loop s2
45 
46     mov ax, 4c00H
47     int 21H
48 code ends
49 end start

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

       

  上图中 076A:0000 - 076A:000f 中内容对应data1内存空间数据,076A:0010 - 076A:001f 对应data2内存空间数据,076A:0020 - 076A:002f 对应data3内存空间数据。

   依次相加之后,查看逻辑段data1, data2, data3对应的内存空间数据原始值的debug命令和截图如下:

  

 

   类似地,data1, data2, data3内存空间数据分别是 076A:0000 - 076A:000f,076A:0010 - 076A:001f,076A:0020 - 076A:002f 中对应的内容。

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

 

实验任务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 code segment
12 start:
13     mov ax, data1
14     mov ds, ax
15 
16     mov ax, data2
17     mov ss, ax
18     mov sp, 16
19 
20     mov bx, 0
21     mov cx, 8
22 s:  push ds:[bx]
23     add bx, 2 
24     loop s
25 
26     mov ax, 4c00h
27     int 21h
28 code ends
29 end start

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

    

 

  在上图中,076A:0000 - 076A:000f 中内容对应data1内存空间数据,076A:0010 - 076A:001f 对应data2内存空间数据。

  可见,程序成功实现了将把逻辑段data1中的8个字数据逆序存储到逻辑段b中的功能。

 

实验任务5

  • task5.asm的源码如下:
 1 assume cs:code, ds:data
 2 data segment
 3         db 'Nuist'
 4         db 2, 3, 4, 5, 6
 5         ;db 5 dup(2)
 6         ;db 5 dup(5)
 7 data ends
 8 
 9 code segment
10 start:
11         mov ax, data
12         mov ds, ax
13 
14         mov ax, 0b800H
15         mov es, ax
16 
17         mov cx, 5
18         mov si, 0
19         mov di, 0f00h
20 s:      mov al, [si]
21         and al, 0dfh
22         mov es:[di], al
23         mov al, [5+si]
24         mov es:[di+1], al
25         inc si
26         add di, 2
27         loop s
28 
29         mov ah, 4ch
30         int 21h
31 code ends
32 end start
  • 运行结果:

  line4是 db 2,3,4,5,6 时,运行结果截图如下:

       

  可以看到,五个字符呈现不同颜色。

    line4是 db 5 dup(2) 时,运行结果截图如下:

    

  可以看到, 五个字符均呈绿色。

  line4是 db 5 dup(2) 时,运行结果截图如下:

       

  可以看到, 五个字符均呈紫色。

  •  使用debug工具对程序进行调试,使用g命令一次性执行到程序返回前(即ine25执行之后、line27 执行之前)的截图如下:

       

 

  •  问:源代码中line21(对应于原题中line19)的作用是?

      答:将字母从小写转为大写。

  • 问:源代码中data段line4的字节数据的用途是?

      答:用于程序中设置显示字符的颜色,不同字节数据值对应了不同的颜色。

 

实验任务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    mov si, 0 
15 
16    mov cx, 4
17 s: mov al, ds:[si]
18    or al, 20H 
19    mov ds:[si], al
20    add si, 16
21    loop s
22 
23    mov ah, 4ch
24    int 21h
25 code ends
26 end start
  • 程序退出前,在debug中使用d命令查看数据段data对应的内存空间的截图如下:

       

 

   可以看到,程序成功实现了将data段中的每行第一个单词从大写转为小写的功能。

 

实验任务7

  • task7.asm的源码如下:
 1 assume cs:code, ds:data, es:table
 2 
 3 data segment
 4     db '1975', '1976', '1977', '1978', '1979' ;一个数字占4个字节,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 si,0
21     mov bx,0
22     mov cx,5
23 s:
24     mov ax,[bx+2]          ;写入年份
25     mov es:[di+2],ax
26     mov ax,[bx]
27     mov es:[di],ax
28 
29     mov ax,[si+20]          ;写入收入
30     mov es:[di+5],0
31     mov es:[di+7],ax
32 
33     mov ax,[si+30]          ;写入雇员数
34     mov es:[di+11],ax
35     mov es:[di+9],0
36 
37     mov ax,es:[di+7]         ;计算人均收入并写入
38     div byte ptr es:[di+11]
39     mov byte ptr es:[di+13],0
40     mov es:[di+14],al
41 
42     add bx,4
43     add si,2
44     add di,16
45     loop s
46 
47     mov ah, 4ch
48     int 21h
49 code ends
50 end start
  • 在debug中运行到程序退出之前,使用d命令查看table段对应的内存空间的截图如下:

       

  可见,信息已经成功结构化地写入到了指定内存。

 

posted @ 2021-11-12 09:34  铃园轻梦  阅读(42)  评论(6编辑  收藏  举报