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

实验任务1-1

源码:

 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

 

 

 现在进入到17行执行后,19行执行前

ds=076c, ss=076d, cs=076e

ds=x-2h,    ss=x-1h,    cs=x

 

任务1-2

源码:

 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

 

 ds=076c, ss=076d, cs=076e

ds=x-2h,    ss=x-1h,    cs=x

 

任务1-3

源码:

 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

 

 ds=076c, ss=076e, cs=0770

ds=x-4h,  ss=x-2h,  cs=x

 

任务1-4

源码:

 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

 

 ds=076e, ss=0770, cs=076c

ds=x+2h,  ss=x+4h, cs=x

任务1-5

 

ceil(N/16) N除以16的结果再向上取整

 

 task1_4.asm是可以执行的

不写 start,程序从头开始执行
写了 start,程序从 start:标号处开始执行。

而task1_4.asm start标号就在程序头部,所以end后面有没有start都是从头开始到最后结束

 

任务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,0403h
 8 
 9     mov cx,80
10     s:
11     mov ds:[bx],ax
12     add bx,2
13     loop s 
14 
15     mov ah, 4ch
16     int 21h
17 code ends
18 end start

几个细节说明一下:ax=0403,题目要求是从低位到高位是0304所以这里要反一下;160个字节,每次填充两个字节,填充80次,cx=80 bx每次增加2

 

 

 这是程序执行之后,目标内存单元的内容如上图所示

 

 

任务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 ax, data2
18     ; mov ax, data3
19     mov ds,ax
20     mov bx,0
21     mov cx,10h
22     s:
23     mov ax,ds:[bx]
24     add ax,ds:[bx+10h]
25     mov ds:[bx+20h],ax
26     inc bx
27     loop s
28 
29     mov ah, 4ch
30     int 21h
31 code ends
32 end start

 

 

 

 为了确定各个数据段的位置和大小,先用工具查看一下。可以看到

data1 起始地址076c:0 长度16字节

data2 起始地址076d:0 长度16字节

data3 其实地址076e:0 长度16字节

 

 反汇编截图

 

 

 这是在相加前的内存单元的内容,里面的数据是16进制的

 

 这是在相加结束之后的,内存单元的值

 

任务4

data1 起始地址076c:0 16字节

data2 起始地址076d:0 16字节

stack 其实地址076e:0

完整代码:

 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 segment
12 stack ends
13 
14 code segment
15 start:
16     mov ax, data1
17     ; mov ax, data2
18     ; mov ax, stack
19     mov ds,ax
20     mov bx,0
21     mov sp,9    ;7+2
22     mov cx,8
23     a:
24     push [bx]
25     add bx,2
26     loop a
27 
28     mov ax,data2 
29     mov ds,ax
30     mov bx,0
31     mov cx,8
32     b:
33     pop [bx]
34     add bx,2
35     loop b
36 
37     mov ah, 4ch
38     int 21h
39 code ends
40 end start

分析:要求逆序存储,很容易会想到用栈的结构,于是构造一个栈段,把它和ss关联。

栈空间是0-7,sp指向7+2=9。

先把8个数进栈,然后改一下地址,再出栈就好了

 反汇编 

 

 在出栈之后,data2内存段的内容逆序存放了目标数字

 

任务5

源码:

 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

运行结果如下:

 

由上表可知,line19的and操作,让该字符的第五位变成0,把小写字母转成对应的大写字母

 

 

 在修改成5 dup(2)后,输出则变成了绿色,由此可见,这一段内存数据控制的是显示的颜色

 

任务6

源码如下:

 

 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 bx,0
16     mov cx,4
17     a:
18     mov di,cx
19     mov cx,4
20         b:
21         mov dl,[bx]
22         or dl,00100000b
23         mov [bx],dl
24         inc bx
25         loop b
26 
27     mov bx,0
28     inc ax  ;进入下一行
29     mov ds,ax
30     mov cx,di
31     loop a
32 
33 
34     mov ah, 4ch
35     int 21h
36 code ends
37 end start

 

在程序执行前,查看内存

 

 

 

然后程序执行到返回前

 

快速执行到21的位置

 

 

 

然后查看内存

 

 

解析:一共四个句子,要对每个句子的前四个字母转换,所以是4*4的循环

我们用cx记录循环,但是有两个循环,所以中间需要用di保存一下外循环计数

大转小,or 00100000b

转到下一行,因为一行16字节,所以直接ax+1,注意,ax中间不能被覆写。所以中间的寄存器我用dx代替了。

 

 

任务7

代码:

 1 assume cs:code, ds:data, es:table
 2 
 3 data segment
 4     db '1975', '1976', '1977', '1978', '1979'
 5     ;20byte  4*5
 6 
 7     dw  16, 22, 382, 1356, 2390
 8     ;10byte  2*5
 9 
10     dw  3, 7, 9, 13, 28 
11     ;10byte  2*5
12 
13 data ends
14 
15 table segment
16     db 5 dup( 16 dup(' ') )  ;80byte
17 table ends
18 
19 code segment
20 start:
21     mov ax,data
22     mov ds,ax
23     mov ax,table
24     mov es,ax
25 
26     mov bx,0
27     mov dx,0
28     mov si,20
29     mov di,0
30 
31     mov cx,5
32     
33     s:
34     mov ax,[bx]
35     mov es:[di],ax
36     mov ax,[bx+2]
37     mov es:[di+2],ax
38     ;年份的存放
39 
40     mov ax,[bx+si]
41     mov es:[di+5],ax
42     ;收入的存放
43 
44     mov dx,[bx+si+10]
45     mov es:[di+10],dx
46     ;雇员数
47 
48     div byte ptr [bx+si+10]
49     mov es:[di+13],al
50     ;平均收入
51 
52 
53     add bx,4
54     sub si,2
55     add di,16
56 
57     loop s
58 
59 
60     mov ah, 4ch
61     int 21h
62 code ends
63 end start

 

 

这是程序运行前,各内存单元的值

 

 

 分析:一共五行,可以做五个循环,每次读入一行的数据。

这里有个坑,我一开始以为日期与收入和人数的距离是固定的20字节和30字节,然后出现了除0的错误。就是我访问的内存超出了原先数据的区域。

然后再反复debug的过程中我发现随着日期的递进,他们与对应的收入和人数的距离每次减少2字节。于是我每次手动减去两个字节才能成功执行程序

 

posted @ 2021-11-06 17:02  星穹铁道  阅读(55)  评论(1)    收藏  举报