实验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之前截图

 

问题回答

① 在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 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之前观察寄存器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 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之前观察寄存器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 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调试到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*(N/16+1)  

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

task1_4.asm仍可以正确执行

task1_4修改前后:

task1_1修改前后:

 

编译器默认从代码的开始位置执行,因为不论修改前后,task1_4.asm代码开始位置就是代码段,所以两个CS:IP值相同并不影响程序执行。而其余汇编程序起始地址是数据段定义,只有在start:标记地方,编译器才知道是代码段的起始地址,因此两个CS的值不同,所以会影响代码段的执行。


 

2. 实验任务2

汇编源代码

 

 1 assume cs:code
 2 code segment
 3     mov ax,0b800h
 4     mov ds,ax
 5     mov bx,0f00h
 6     mov cx,80
 7 
 8   s:mov ds:[bx],0403h
 9     add bx,2
10     loop s
11 
12     mov ax,4c00h
13     int 21h
14 code ends
15 end

 

03 04 当作字单元存储 03低地址 04高地址,因此该字为0403h

运行结果截图


 

3. 实验任务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 code segment
15 start:
16     mov ax,data1
17     mov ds,ax
18     mov cx,16
19     mov bx,0
20   
21   s:mov al,ds:[bx]
22     add al,ds:[bx+16]
23     mov ds:[bx+32],al
24     inc bx
25     loop s
26     
27     mov ah,4ch
28     int 21h
29 code ends
30 end start

 

在debug中加载、反汇编、调试截图

 

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

 

 

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

 

 


 

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

 

在debug中加载、反汇编、调试截图

 

要求给出,在程序退出前,使用d命令查看数据段data2对应的内存空间的截图。


 

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命令一次性执行到程序返回前(即ine25执行之后、line27执行之前)的截图

源代码中line19的作用是?

作用是:如果低位地址是小写字母,将其变成大写字母,通过按位与,将对应小写字母的Ascii码二进制的第五位变成0,也就是Ascii值减去32即变成大写字母。

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

改成:db 5 dup(2)

 

 

 改成:db 5 dup(5)

 

 

用途是设置显示字符的前景色

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    mov cx, 4
15    mov bx, 0
16    
17 s1:
18    mov dx, cx    ; 存储外层循环的cx
19    mov cx, 4
20    mov si, 0
21    s2:
22       or byte ptr [bx+si], 020h
23       inc si
24    loop s2
25    mov cx, dx
26    add bx, 16
27 loop s1    
28 
29    mov ah, 4ch
30    int 21h
31 code ends
32 end start

 

在debug中加载、反汇编、调试截图

 

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

 


 

7. 实验任务7

task7.asm源码

 

 1 assume cs:code, ds:data, es:table
 2 
 3 data segment
 4     db '1975', '1976', '1977', '1978', '1979' 
 5     dw  16, 22, 382, 1356, 2390
 6     dw  3, 7, 9, 13, 28 
 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,table;table段首地址赋值给数据段寄存器
16     mov ds,ax
17 
18     mov ax,data;data段首地址赋值给附加数据段寄存器
19     mov es,ax
20 
21 ;移入年份
22     mov cx,5
23     mov bx,0;ds的偏移地址
24     mov si,0;es的偏移地址
25 s_year: 
26     mov ax,es:[si];先移入前一个字单元,即两个字节单元
27     mov [bx],ax
28     mov ax,es:[si+2];再后一个字单元,一行结束
29     mov [bx+2],ax
30     add si,4;指向下一个年份首地址
31     add bx,16;指向第二行
32     loop s_year
33 
34 ;移入收入
35     mov cx,5
36     mov bx,5;从空格后开始
37 s_salary:
38     mov ax,es:[si]
39     mov [bx],ax
40     mov word ptr [bx+2],0000h;后两个字节为空
41     add si,2
42     add bx,16
43     loop s_salary
44    
45 ;移入雇员数
46     mov cx,5
47     mov bx,10
48 s_employee:
49     mov ax,es:[si]
50     mov [bx],ax
51     add si,2
52     add bx,16
53     loop s_employee
54 
55 ;计算并移入人均收入
56     mov cx,5
57     mov bx,5
58 s_gdp:
59     mov ax,[bx];存入被除数的低8位
60     mov dx,[bx+2];存入被除数的高8位
61     div word ptr [bx+5]
62     mov [bx+8],ax
63     add bx,16
64     loop s_gdp
65    
66     mov ah, 4ch
67     int 21h
68 code ends
69 end start

 

调试截图

 

查看table段原始数据信息截图

 

在debug中运行到程序退出之前,使用d命令查看table段对应的内存空间的截图,确认信息是

否按要求结构化地写入到指定内存

 

被除数32位  除数16位

五、实验总结 

1.直接写显存 0b800h 显示 字符串

 

显示字符就是往显存里写进要显示的东西。每个字符占显存中两个字节,低字节是字符的ASCII码,高字节是设置所示字符的属性。

每位都定义有显示属性,从高位到低位依次是:闪烁   背景红   背景绿   背景蓝   高亮   前景红   前景绿   前景蓝

 

2.当输入一个外部命令或通过EXEC子功能(系统功能调用INF 21h的子功能号为4BH)加载一子程序时,COMMAND确定当时内存可用空间的最低端作为程序段起点。在程序所占内存空间的前256个字节中,系统会为程序创建程序的前缀(PSP)的数据区,DOS要利用PSP来和被加载程序进行通信;PSP内有程序返回、程序文件名等信息,可以通过研究psp定位文件名信息,进而获取文件名。

从这段内存区的256字节处开始(在PSP的后面),将程序装入,程序的地址被设为SA+10H:0 (其中SA为系统为程序分配内存的起始位置的段地址即当前寄存器DS的内容)。

 

3.汇编语言的DIV指令是除法指令

A / B  A是被除数,B是除数

除数B有 8位和16位两种,保存在一个reg寄存器里 或是内存单元中。

被除数A 默认存放在AX中(16位以内) 或 AX和DX中(32位,DX存放高16位,AX存放低16位)

结果:如果除数B是8位,那么除法的结果AL保存商,AH保存余数,

   如果除数B是16位,那么除法的结果 AX保存商,DX保存余数。

公式如下:

    1: div byte ptr ds:[0]

   含义:(al) = (ax)/((ds)*16+0) 的商

       (ah) = (ax/(ds)*16+0) 的余数

    2:div word ptr es:[0]

   含义:(ax) = [(dx)*10000H+(ax)] / ((es)*16+0)的商

      (dx) = [(dx)*10000H+(ax)] / ((es)*16+0)的余数

    3:div byte ptr [bx+si+8]

   含义:(al) = (ax) / ((ds)*16+(bx)+(si)+8) 的商

      (ah) = (ax) / ((ds)*16+(bx)+(si)+8) 的余数

    4:div word ptr [bx+si+8]

   含义:(ax) = [(dx)*10000h+(ax)] / ((ds)*16+(bx)+(si)+8) 的商

      (dx) = [(dx)*10000h+(ax)] / ((ds)*16+(bx)+(si)+8) 的余数

posted @ 2021-11-10 16:18  sshen270  阅读(66)  评论(3)    收藏  举报