实验3 多个段的汇编源程序编写与调试
一、实验目的
二、实验准备
三、实验内容
1. 实验任务1
录入汇编源程序task1.asm:
assume cs:code, ds:data data segment db 'Nuist' db 5 dup(2) data ends code segment start: mov ax, data mov ds, ax mov ax, 0b800H mov es, ax mov cx, 5 mov si, 0 mov di, 0f00h s: mov al, [si] and al, 0dfh mov es:[di], al mov al, [5+si] mov es:[di+1], al inc si add di, 2 loop s mov ah, 4ch int 21h code ends end start
mov cx, 5 //设置循环次数为5次(Nuist有5个字节) mov si, 0 //设置偏移量,这是设置数据段ds的偏移地址 mov di, 0f00h //设置es的偏移地址 s: mov al, [si] //将ds:[si]一个字节的内容存入al and al, 0dfh //将字母大写 mov es:[di], al //将al里的数据存入附加段里面去,这里存入的是数据信息 mov al, [5+si] //将ds:[5+si]存入al mov es:[di+1], al //再次存入到附加段里面去,这次是存在高位上面,是颜色信息 inc si //si自加 add di, 2 //附加段的偏移地址加2,移动一个字的单位 loop s //循环
这段代码的目的是将 “Nuist”字母变成大写,再将颜色都设置成绿色。
编译,链接,执行得到结果



db 5 dup(2) --> 改成: db 2,3,4,5,6

这里的数值代表的是颜色信息,因为是把这些数字都送到了字母的高位字节里去了。
2. 实验任务2
data segments db 23, 50, 66, 71, 35 data ends
assume cs:code, ds:data data segment db 23,50,66,71,35 data ends code segment start: mov ax, data mov ds, ax mov cx, 5 mov si, 0 s: mov ah, 0 //因为这个数太小,所以并且是一个字节存储,所以高位先赋0 mov al, [si] mov bl,10 div bl mov ds:[8],al //存放商,即十位上的数 mov ds:[9],ah //存放余数,即个位上的数 mov ah,2 mov dl,ds:[8] add dl,30h int 21h mov ah,2 mov dl,ds:[9] add dl,30h int 21h //用,间隔 mov ah,2 mov dl,"," int 21h inc si loop s mov ah, 4ch int 21h code ends end start
运行结果:

查看ds存放,前面是5个是存放的数据,ds[8],ds[9]存放的是最后一次的商和余数3,5
![]()
3. 实验任务3
assume cs:code, ds:data, ss:stack data segment dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h data ends stack segment dw 0, 0, 0, 0, 0, 0, 0, 0 stack ends code segment start: mov ax,stack mov ss, ax mov sp,16 mov ax, data mov ds, ax push ds:[0] push ds:[2] pop ds:[2] pop ds:[0] mov ax,4c00h int 21h code ends end start
反汇编,同时查询ds里存放的数据:0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h

-g 1d 执行程序,得到 cs=076ch,ss=076bh,ds=076ah
查看ds里的数据没有发生变化,仍然是:0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h

因此:
1.CPU执行程序,程序返回前,data段中的数据:0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h
2.CPU执行程序,程序返回前,cs=076ch,ss=076bh,ds=076ah
3.设程序加载后,code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1。
4. 实验任务4
assume cs:code, ds:data, ss:stack data segment dw 0123h, 0456h data ends stack segment dw 0, 0 stack ends code segment start: mov ax,stack mov ss, ax mov sp,16 mov ax, data mov ds, ax push ds:[0] push ds:[2] pop ds:[2] pop ds:[0] mov ax,4c00h int 21h code ends end start
汇编、链接后进入debug,进行反汇编(记得老师说过一个段最小是16字节,所以数据段加上栈段虽然都不满16字节,但是都按照16字节算,总共32字节)
查看data中的数据:0123h, 0456h, 0, 0, 0, 0, 0, 0

-g 1d 执行程序,得到 cs=076ch,ss=076bh,ds=076ah
查看ds里的数据没有发生变化,仍然是:0123h, 0456h, 0, 0, 0, 0, 0, 0

因此:
1.CPU执行程序,程序返回前,data段中的数据:0123h, 0456h, 0, 0, 0, 0, 0, 0
2.CPU执行程序,程序返回前,cs=076ch,ss=076bh,ds=076ah
3.设程序加载后,code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1。
4.对如下定义的段:
name segment
···
name ends
如果段中的数据占 N 个字节,不是16字节的整数倍,则会补整,则程序加载后,该段实际占用的空间为:[(N+15)/16]*16([ ]为取整符号)
5. 实验任务5
assume cs:code, ds:data, ss:stack code segment start: mov ax,stack mov ss, ax mov sp,16 mov ax, data mov ds, ax push ds:[0] push ds:[2] pop ds:[2] pop ds:[0] mov ax,4c00h int 21h code ends data segment dw 0123h, 0456h data ends stack segment dw 0,0 stack ends end start
反汇编,然后运行到将数据段地址赋给ds,然后查看数据段中的数据:0123h, 0456h, 0, 0, 0, 0, 0, 0

-g 1d 执行程序,得到 cs=076ah,ss=076Eh,ds=076dh
查看ds里的数据没有发生变化,仍然是:0123h, 0456h, 0, 0, 0, 0, 0, 0

因此:
1.CPU执行程序,程序返回前,data段中的数据:0123h, 0456h, 0, 0, 0, 0, 0, 0
2.CPU执行程序,程序返回前,cs=076ah,ss=076Eh,ds=076dh
3.设程序加载后,code段的段地址为X,则data段的段地址为X+3,stack段的段地址为X-4。
6. 实验任务6
7. 实验任务7
assume cs:code a segment db 1,2,3,4,5,6,7,8 a ends b segment db 1,2,3,4,5,6,7,8 b ends c segment db 8 dup(0) c ends code segment start: mov ax,a mov ds,ax mov si,0 mov cx,9 s: mov ax,0 mov al,[si] add al,[si+16] mov [si+32],al inc si loop s mov ah,4ch int 21h code ends end start
因为a,b,c段的长度都是16,所以就直接通过加偏移量16 32来进行访问
使用-g 19执行,查看a,b,c的数据,看到最后一行的数据是由前面两行相加得到的,满足要求。
8. 实验任务8
程序源码见task8.asm:
assume cs:code a segment dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh a ends b segment dw 8 dup(0) b ends code segment start: mov ax,b mov ss,ax mov sp,10h mov ax,a mov ds,ax mov si,0 mov cx,9 s: push ds:[si] add si,2 loop s mov ah,4ch int 21h code ends end start
反汇编后得知程序在 001ah处返回,使用 -g 001a命令

因为题目要求是逆序存储,所以首先想到就是将b段当成栈段,然后将a里的数据不断地压入栈,实现逆序存储,从上图中查看的结果看出结果满足实验要求,实现了逆序存储。
四、实验总结
1.各逻辑段在内存空间中依序排列,并以 16 个字为一个单元进行分配;若 code 段前有自己设置的逻辑段,需要指明程序的入口,要加上end start。
2.在实验1中的查看大写的nuist存放的地方查看出来和自己预想的不一样,有些困惑。

浙公网安备 33010602011771号