实验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字节。于是我每次手动减去两个字节才能成功执行程序

浙公网安备 33010602011771号