(1) 将下面的程序编译、连接、用Debug加载、跟踪、然后回答问题
assume cs:code,ds:data,ss:stack data segment dw 0123,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
①CPU执行程序,程序返回前,data段中的数据为多少?
解答:我们先用debug加载跟踪一下看看结果如何
在程序刚载入内存时,由于还没有执行设定数据段地址的指令(mov ds,data),DS段地址默认指向程序起始位置(包括PSP数据区),此时 DS:0~DS:FF 为PSP数据区(占256个字节),DS:100 开始为数据段、栈段、代码段内容。(如上图)
在执行了mov ds,data 指令后,数据段被手工设定为 DS:0~D:F为数据段(DS段地址已经被更改)(如下图)但在设定逻辑上的数据段前后,物理上的数据段是始终没有发生改变的,始终处于 1299:0~1299:f 部分
由实验结果可知,data段中的数据为
23 01 56 04 89 07 BC 0A EF 0D ED 0F BA 0C 87 09
②CPU执行程序,程序返回前,CS = ______ 、SS= ______ 、DS= ______
执行到 mov ax,4c00h指令时,各寄存器内容如下
由实验结果可知 CS = 129B ,SS = 129A,DS = 1299
③设程序加载后,code段的段地址为X,则data段的段地址为_____,stack段的段地址为_____。
由②可知 DS = CS - 2,SS = CS - 1。
故 data 段地址为 X - 2,stack 段地址为 X - 1
(2)将下面的程序编译、连接,用 Debug 加载、跟踪,然后回答问题
assume cs:code,ds:data,ss:stack data segment dw 0123,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
① CPU执行程序,程序返回前,data段中的数据为多少?
注意:数据段和栈段在程序加载后实际占据的空间都是以 16 个字节为单位的,如果不足,以 0 补全填充
由实验结果可知,data段中的数据为
23 01 56 04 00 00 00 00 00 00 00 00 00 00 00 00
② CPU执行程序,程序返回前,CS = ______ 、SS= ______ 、DS= ______
由实验结果可知 CS = 129B ,SS = 129A,DS = 1299
③ 设程序加载后,code段的段地址为X,则data段的段地址为,stack段的段地址为。
这里与(1)大致相同,因为段的结构顺序和大小是大致相同的
由②可知 DS = CS - 2,SS = CS - 1。
故 data 段地址为 X - 2,stack 段地址为 X - 1
④ 对于如下定义的段:
name segment
...
name ends
如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为
如果N小于16,那么实际占用16个字节;如果N大于16,那么实际占用(N/16的取整数+1)*16个字节。即如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为
(3)将下面的程序编译、连接,用 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 0123,0456h data ends stack segment dw 0,0 stack ends end start
① CPU执行程序,程序返回前,data段中的数据为多少?
(3)与(1)(2)所不同的是(3)将数据段和栈段放到了代码段的后面
由实验结果可知,data段中的数据为
23 01 56 04 00 00 00 00 00 00 00 00 00 00 00 00
② CPU执行程序,程序返回前,CS = ______ 、SS= ______ 、DS= ______
由实验结果可知 CS = 1299 ,SS = 129D,DS = 129C
③ 设程序加载后,code段的段地址为X,则data段的段地址为,stack段的段地址为。
由②可知 DS = CS + 3,SS = CS =+ 4
故data段的段地址为 X + 3,stack段的段地址为 X + 4
(4)如果将(1)、(2)、(3)题中的最后一条伪指令“end start”改为“end”(也就是说,不指明程序的入口),则哪个程序仍然可以正确执行?请说明原因。
在程序设计中,我们用伪指令end描述了程序的结束和程序的入口。在编译链接后,由“end start”指明的程序入口,被转化为一个入口地址,我们可以发现在程序中设置了start 和 end start 后 程序执行时会从 start 位置开始,到 end start 位置结束。如果不设 end start ,只设置 end 。那么此时程序会默认从 PSP数据区后开始执行(即使设置了start,程序也不会从start位置开始执行)。如果要保证程序正常执行,那么在PSP数据区之后必须为代码段才行。由(1)(2)(3)三个程序可知只有程序(3)代码段在前面,故最后一条伪指令“end start”改为“end”后,程序(3)仍然可以正确执行
(5)程序如下、编写 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 segment code segment start: ___________ code ends end start
这里首先要注意的是,a 段、b 段和 c 段的数据都是按字节存放的,所以在使用寄存器转移数据时一定要使用 8 位寄存器而不是 16 位寄存器!不然就有可能引起错误(虽然本题使用 16 位寄存器与使用 8 位寄存器结果一样,但一定要规范)。
这里笔者使用的思想是使用 DS 存储 a 段地址,b 段地址可以直接使用 DS + 16 表示(a 段不足16个字节用 0 补上后占 16 个字节) ES 存储 c 段地址,每次循环将 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: mov ax,a mov ds,ax ; ds 存放 a 段地址 mov ax,c mov es,ax ; es 存放 c 段地址 mov bx,0 mov cx,8 ; 对字进行 8 次循环操作 s0: mov dl,[bx] add dl,[bx+16] // a 段不足16个字节用0补上后占16个字节 mov es:[bx],dl // a + 16 后即为 b 段地址 inc bx loop s0 mov ax,4c00h int 21h code ends end start
实验结果如下:
(6)程序如下,编写code段中的代码,用 push 命令将 a 段中的前 8 个字型数据,逆序存储到 b 段中。
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 0,0,0,0,0,0,0,0 b ends code segment start: __________ code ends end start
本题与上一题有所不同,本题是数据是按字存储的,故使用 16 位寄存器。
要求使用 push 指令将前 8 个字型数据存储到 b 段中,这里应当a段为数据段、 b 段为栈段才能使用 push 指令将 a 段的数据压入 b 段中,循环 8 次即可
代码如下:
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 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,10h mov bx,0 mov cx,8 s0: push [bx] ; a 段数据压入 b 段 inc bx ; 由于字占 16 位,一个内存单元占 8 位 inc bx ; 故每次循环 + 2 才能指到下一个字 loop s0 mov ax,4c00h int 21h code ends end start
实验结果如下: