编写、调试具有多个段的程序

  • 实验内容、程序清单及运行结果
  1. 编写下述程序并运行,然后用 Debug 加载、跟踪。

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,4c20h

int 21h

code ends

end start

以下单步执行:

由图可知:

  • CPU 执行程序,程序返回前,data 段中的数据为 没有变化。

解释:end start 指明程序将标号 start 作为程序入口,代码段部分分为以下功能:定义空栈,设置寄存器 DS 的值,两次入栈,两次出栈。由于两次入栈出栈的地址逆序,且都是针对 DS 操作,所以以寄存器 DS 为标识的代码段部分数据没有改变。

  • CPU 执行程序,程序返回前,cs= 079C、ss= 079D、ds= 0042

解释:

  • 设程序加载后,code 段的段地址为 X,则 data 段的段地址为 X-2,stack 段的段地址为 X-1

解释:

由此得知,系统以各段的定义顺序为各段分配空间,并且空间以 16 字节对齐。

  1. 编写下述程序并运行,然后用 Debug 加载、跟踪。

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,4c20h

int 21h

code ends

end start

  • CPU 执行程序,程序返回前, data 段中的数据为 前 4 个字节存放定义的数据、后面为填充数据

  • CPU 执行程序,程序返回前,cs= 079E、ss= 079D、ds=079C
  • 设程序加载后,code 段的段地址为 X,则 data 段的段地址为 X-2,stack 段的段地址为 X-1
  • 对于如下定义的段:

name segment

...

name ends

如果段中的数据占 N 个字节,则程序加载后,该段实际占有的空间为 N/16*16+(N%16!=0)*16。

解释:前面由实验得知,各段的大小在实际存储时有 16 字节的对齐。所以,当 N 能整除 16 时,该段实际占用空间为 N;当 N 不能整除 16 时,占有的空间向上 16 字节对齐。

  1. 编写下述程序并运行,然后用 Debug 加载、跟踪。

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

  • CPU执行程序,程序返回前,data段中的数据为多少?
  • CPU执行程序,程序返回前,cs=079ch,ss=07a0h,ds=079fh.
  • 设程序加载后,code段的短地址为x,则data段的短地址为__x+3__,stack段的短地址为__x+4__。
  1. 如果将上面三题中最后一条伪指令 end start 改为 end,则哪个程序仍可以正确执行。

end start 指明程序入口为 start 标号处,没有指明程序入口时程序将从加载的第一条指令开始执行,所以只有(3)能够正确运行。这里也可以看出,代码和数据在内存中的存放形式都是一致的,关键是编写代码的人去控制 CPU 执行指令实为指令的代码、使用实为数据的代码。所以,在编写程序时最好指定程序入口。

  1. 编写 code 段中的代码,将 a 段和 b 段中的数据依次相加,将结果存到 c 段中。

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 0,0,0,0,0,0,0,0

c ends

code segment

start:

?

code ends

end start

题目要求将两个段 a 和 b 的内容依次相加,将相加结果存入另一个段 c 中,每个段的大小都是 8 个字节。即,考虑首先将段 a 的内容复制到 段 c 中,然后再将段 b 和段 c 的内容相加,在代码部分使用两个循环。

首先,我们需要使用段寄存器指向某个段,段寄存器有 CS、DS、SS、ES,CS 用于代码段的管理、SS 用于栈段的管理,这里使用 DS 和 ES 两个段寄存器。待完成部分:

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 0,0,0,0,0,0,0,0

c ends

code segment

start:

mov ax,a

mov ds,ax

mov ax,c

mov es,ax ;使用段寄存器ES指向段c

mov cx,8 ;定义循环次数,一共有8个字节的数据

mov bx,0 ;定义偏移量

s1: mov al,ds:[bx] ;每次处理1个字节

mov es:[bx],al

inc bx ;每次偏移1个字节

loop s1 ;第一个循环完成将段a的内容复制到段c

mov ax,b ;移动

mov ds,ax ;使用段寄存器DS指向段b

mov cx,8 ;定义循环次数,一共有8个字节的数据

mov bx,0 ;定义偏移量

s2: mov al,ds:[bx] ;每次处理1个字节

add es:[bx],al ;相加

inc bx ;每次偏移1个字节

loop s2 ;第二个循环完成段b和段c的内容相加

mov ax,4c00h ;程序返回

int 21h

code ends

end start

  1. 编写 code 段中的代码,用 push 指令将 a 段中的 word 数据,逆序存储到 b 段中。

assume cs:code

a segment

dw 1,2,3,4,5,6,7,8

a ends

b segment

dw 0,0,0,0,0,0,0,0

b ends

code segment

start:

?

code ends

end start

题目要求逆序存放,利用栈先进后出的特点即可。由于入栈时栈顶寄存器 SP 的值减小而出栈时 SP 的值增大。所以,直接将段 a 中的数据入栈,同时将段 b 作为栈段,即可将段 a 中的字数据逆序存放到段 b 中。

assume cs:code

a segment

dw 1,2,3,4,5,6,7,8

a ends

b segment

dw 0,0,0,0,0,0,0,0

b ends

code segment

start:

mov ax,a

mov ds,ax ;使用段寄存器DS指向段a

mov ax,b

mov ss,ax ;使用段寄存器SS指向段b

mov sp,16 ;初始化空栈,SP指向栈顶的下一个位置

mov cx,8 ;循环次数

mov bx,0 ;偏移量

s: push ds:[bx]

add bx,2 ;每次偏移一个字

loop s

mov ax,4c00h;程序返回

int 21h

code ends

end start

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值