|
主题 : : 实验5 编写、调试具有多个段的程序 刚做好 发出来让大家看看有没错误 谢谢 [待解决] |
回复[ 9次 ]
点击[ 377次 ] | |
|
|
|
|
[帖 主]
[ 发表时间:2011-11-22 14:53 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2011-10-05 19:31 |
这一章的内容较少,有些知识需要在实践中掌握。这个实验,即是实验,也是学习内容。必须完成这个实验,才能继续向下学习。
(1)将下面的程序编译连接,用Debug加载、跟踪,然后回答问题。
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
①CPU执行程序,程序返回前,data段中的数据为多少?
②CPU执行程序,程序返回前,cs=13d5、ss=13d4、ds=13d3。
③设程序加载后,code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1。
调试过程如下:
-r
AX=0000 BX=0000 CX=0042 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=13C3 ES=13C3 SS=13D3 CS=13D5 IP=0000 NV UP EI PL NZ NA PO NC
13D5:0000 B8D413 MOV AX,13D4
-g 13d5:001d
AX=13D3 BX=0000 CX=0042 DX=0000 SP=0010 BP=0000 SI=0000 DI=0000
DS=13D3 ES=13C3 SS=13D4 CS=13D5 IP=001D NV UP EI PL NZ NA PO NC
13D5:001D B8004C MOV AX,4C00
-d 13d3:0000
13D3:0000 23 01 56 04 89 07 BC 0A-EF 0D ED 0F BA 0C 87 09 #.V.............
13D3:0010 00 00 00 00 00 00 00 00-00 00 1D 00 D5 13 DB 0D ................
13D3:0020 B8 D4 13 8E D0 BC 10 00-B8 D3 13 8E D8 FF 36 00 ..............6.
13D3:0030 00 FF 36 02 00 8F 06 02-00 8F 06 00 00 B8 00 4C ..6............L
13D3:0040 CD 21 00 00 00 00 00 00-00 00 00 00 00 00 00 00 .!..............
13D3:0050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13D3:0060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13D3:0070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
-r
AX=13D3 BX=0000 CX=0042 DX=0000 SP=0010 BP=0000 SI=0000 DI=0000
DS=13D3 ES=13C3 SS=13D4 CS=13D5 IP=001D NV UP EI PL NZ NA PO NC
13D5:001D B8004C MOV AX,4C00
-
(2)将下面的程序编译连接,用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,4c00h
int 21h
code ends
end start
①CPU执行程序,程序返回前,data段中的数据为多少?
解:
13D3:0000 23 01 56 04 00 00 00 00-00 00 00 00 00 00 00 00 #.V.............
②CPU执行程序,程序返回前,cs=13d5、ss=13d4、ds=13d3。
解:
-g 001d
AX=13D3 BX=0000 CX=0042 DX=0000 SP=0010 BP=0000 SI=0000 DI=0000
DS=13D3 ES=13C3 SS=13D4 CS=13D5 IP=001D NV UP EI PL NZ NA PO NC
13D5:001D B8004C MOV AX,4C00
③设程序加载后,code段的段地址为X,则data段的段地址为X-2,stack段的段地址为X-1。
④对于如下定义的段:
name segment
...
name ends
如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为((N-1)/16+1)*16 N>0 。
解:代码中 data段和stack段中的数据各占4个字节
观察调试过程发现
AX=13D3 BX=0000 CX=0042 DX=0000 SP=0010 BP=0000 SI=0000 DI=0000
DS=13D3 ES=13C3 SS=13D4 CS=13D5 IP=001D NV UP EI PL NZ NA PO NC
13D5:001D B8004C MOV AX,4C00
相关寄存器的值如下:
DS=13D3 SS=13D4 CS=13D5
stack段在 data段之后
用stack段的起始地址减去data段的起始地址 即为data段的实际占有空间 为 (13d4*16+0000)-(13d3*16+0000)=10H,stack段的计算方法一样,然后我们观察code段的实际地址
-u
13D5:0000 B8D413 MOV AX,13D4
13D5:0003 8ED0 MOV SS,AX
13D5:0005 BC1000 MOV SP,0010
13D5:0008 B8D313 MOV AX,13D3
13D5:000B 8ED8 MOV DS,AX
13D5:000D FF360000 PUSH [0000]
13D5:0011 FF360200 PUSH [0002]
13D5:0015 8F060200 POP [0002]
13D5:0019 8F060000 POP [0000]
13D5:001D B8004C MOV AX,4C00
中间略
-t
AX=4C00 BX=0000 CX=0042 DX=0000 SP=0010 BP=0000 SI=0000 DI=0000
DS=13D3 ES=13C3 SS=13D4 CS=13D5 IP=0020 NV UP EI PL NZ NA PO NC
13D5:0020 CD21 INT 21
可见code的起始地址为 13D5:0000 结束地址为 13D5:0020
所以 code段的实际占有的空间为20H。
1,当N<16时,占有16个字节
2,当N/16余数为0时,占有N个字节
3,当N/16商为A,余数不为0时,占有(N/16+1)*16个字节
因为段机制,我们知道一个段最小为16字节,而且是16字节的整数倍,所以,N个字节占用的空间不一定就是N,只有在N为16的整数倍的时候才正好占用N个字节的空间,否则,就会占用(N/16 + 1)*16个字节,不足16整数倍的会填充到16的整数倍。
调试程序过程如下:
-r
AX=0000 BX=0000 CX=0042 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=13C3 ES=13C3 SS=13D3 CS=13D5 IP=0000 NV UP EI PL NZ NA PO NC
13D5:0000 B8D413 MOV AX,13D4
-u
13D5:0000 B8D413 MOV AX,13D4
13D5:0003 8ED0 MOV SS,AX
13D5:0005 BC1000 MOV SP,0010
13D5:0008 B8D313 MOV AX,13D3
13D5:000B 8ED8 MOV DS,AX
13D5:000D FF360000 PUSH [0000]
13D5:0011 FF360200 PUSH [0002]
13D5:0015 8F060200 POP [0002]
13D5:0019 8F060000 POP [0000]
13D5:001D B8004C MOV AX,4C00
-g 001d
AX=13D3 BX=0000 CX=0042 DX=0000 SP=0010 BP=0000 SI=0000 DI=0000
DS=13D3 ES=13C3 SS=13D4 CS=13D5 IP=001D NV UP EI PL NZ NA PO NC
13D5:001D B8004C MOV AX,4C00
-d 13d3:0000
13D3:0000 23 01 56 04 00 00 00 00-00 00 00 00 00 00 00 00 #.V.............
13D3:0010 00 00 00 00 00 00 00 00-00 00 1D 00 D5 13 DB 0D ................
13D3:0020 B8 D4 13 8E D0 BC 10 00-B8 D3 13 8E D8 FF 36 00 ..............6.
13D3:0030 00 FF 36 02 00 8F 06 02-00 8F 06 00 00 B8 00 4C ..6............L
13D3:0040 CD 21 00 00 00 00 00 00-00 00 00 00 00 00 00 00 .!..............
13D3:0050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13D3:0060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13D3:0070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
-t
AX=4C00 BX=0000 CX=0042 DX=0000 SP=0010 BP=0000 SI=0000 DI=0000
DS=13D3 ES=13C3 SS=13D4 CS=13D5 IP=0020 NV UP EI PL NZ NA PO NC
13D5:0020 CD21 INT 21
附:CX中的值
在程序加载的时候,计算CX的值是通过段地址和偏移地址的变动来求得的。
(1)如果程序只有一个段或者是程序中的最后一个段,那么在计算过程中,不涉及段地址的改变,即段地址不变,变的只是偏移地址,所以计算出来偏移地址改变量就是cx的值。
(2)如果是多个段,计算的应该过程是这样的:比如说,整个程序拥有N(N>1)个段,这时CX的值为:前N-1个段占的字节 + 第N个段(即最后一个段)占的字节。其中,第N个段的计算原理见(1);而前N-1个段的计算是按照段地址的变动求得的,与偏移地址没有什么关系,所以,前N-1个段得到的值必然是16的倍数。
举一个具体的例子来说吧。
assume cs:codesg
stack segment
db 'asdf'
stack ends
data segment
db '12345678901234567890'
data ends
codesg segment
start:
mov ax,0
mov bx,0
mov ax , bx
mov ax,4c00h
int 21h
codesg ends
end start
这段程序包含三个段,前两个段占的字节数是通过段地址的变化得到的,即(codesg的段地址-stack的段地址)*16,我们可以不通过debug来求这个值,可以计算出前两个段每个段占的字节数,stack段定义了4个字符,但是,由于不是最后一个段,所以stack段占的字节数按照段地址的增量变化来计算,不足16*1个字节,占16个字节,即10H;同理,data段定义了20个字符,占的字节数为16*2=32,即20H。至于codesg段,是最后一个段,计算的时候依据的是偏移地址的变化来计算,各条指令相加3+3+2+3+2 = DH。所以,最终改程序的CX=10H+20H+DH=3DH
如果以上例子中的程序调整为以下形式:
assume cs:codesg
codesg segment
start:
mov ax,0
mov bx,0
mov ax , bx
mov ax,4c00h
int 21h
codesg ends
stack segment
db 'asdf'
stack ends
data segment
db '12345678901234567890'
data ends
end start
那么第一个段codesg占字节数为10H,第二个段stack占字节数为10H,第三个段data段占字节数为14H,程序总的字节数为10H+10H+14H = 34H。
为什么同一个程序在编译后得到的CX长度不一样,应该比较明显了。
(3)将下面的程序编译连接,用Debug加载、跟踪,然后回答问题。
①CPU执行程序,程序返回前,data段中的数据为多少?
解:
13D6:0000 23 01 56 04 00 00 00 00-00 00 00 00 00 00 00 00 #.V.............
②CPU执行程序,程序返回前,cs=14d3、ss=13d7、ds=13d6。
③设程序加载后,code段的段地址为X,则data段的段地址为X+2,stack段的段地址为X+3。
调试过程如下:
-r
AX=0000 BX=0000 CX=0044 DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=13C3 ES=13C3 SS=13D3 CS=13D3 IP=0000 NV UP EI PL NZ NA PO NC
13D3:0000 B8D713 MOV AX,13D7
-u
13D3:0000 B8D713 MOV AX,13D7
13D3:0003 8ED0 MOV SS,AX
13D3:0005 BC1000 MOV SP,0010
13D3:0008 B8D613 MOV AX,13D6
13D3:000B 8ED8 MOV DS,AX
13D3:000D FF360000 PUSH [0000]
13D3:0011 FF360200 PUSH [0002]
13D3:0015 8F060200 POP [0002]
13D3:0019 8F060000 POP [0000]
13D3:001D B8004C MOV AX,4C00
-g 001d
AX=13D6 BX=0000 CX=0044 DX=0000 SP=0010 BP=0000 SI=0000 DI=0000
DS=13D6 ES=13C3 SS=13D7 CS=13D3 IP=001D NV UP EI PL NZ NA PO NC
13D3:001D B8004C MOV AX,4C00
-d 13d6:0000
13D6:0000 23 01 56 04 00 00 00 00-00 00 00 00 00 00 00 00 #.V.............
13D6:0010 00 00 00 00 00 00 00 00-00 00 1D 00 D3 13 DB 0D ................
13D6:0020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13D6:0030 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13D6:0040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13D6:0050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13D6:0060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13D6:0070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
-
(4)如果将(1)(2)(3)题中的最后一条伪指令"end start” 改为 "end"(也就是说,不指明程序的入口),则哪个程序仍然可以正确执行?请说明原因。
解:第3题可以正确执行,因为第3题代码段就在开始的位置,所以,你懂的~~~~~~~
(5)程序如下,编写code段中的代码,将a段和b段中的数据依次相加,将结果存在c段中。
assume cs:code
a segment
db 1,2,3,4,5,6,7,8
a end
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
解:
assume cs:code
a segment
db 1,2,3,4,5,6,7,8
a end
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,b
mov es,ax
mov ax,c
mov ss,ax
mov bx,0
mov cx,8
s:mov al [bx]
mov ah [bx]
add al,ah
mov ss:[bx],al
inc bx
loop s
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
解:
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
mov ax,b
mov ss,ax
mov sp,16
mov bx,0
mov cx,8
s:push [bx]
add bx,2
loop s
code ends
end start | | |
|
|
|
|
[第1楼]
[ 回复时间:2011-11-22 19:30 ]
[引用]
[回复]
[ top ] | |
荣誉值:405
信誉值:0
注册日期:2008-01-19 14:51 |
|
|
|
|
|
[第2楼]
[ 回复时间:2011-11-24 10:17 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2011-10-05 19:31 |
回复:[第1楼]
------------------
能否指正呢? 谢谢 | | |
|
|
|
|
[第3楼]
[ 回复时间:2011-11-24 20:51 ]
[引用]
[回复]
[ top ] | |
荣誉值:405
信誉值:0
注册日期:2008-01-19 14:51 |
结果是正确的,但是没有看清题意,不是同一个段的数据自加,而是,两个不同的段的数据相加。“将a段和b段中的数据依次相加,将结果存在c段中”。 | | |
|
|
|
|
[第4楼]
[ 回复时间:2011-11-24 21:15 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2011-10-05 19:31 |
回复:[第3楼]
------------------
谢谢提醒啊 写的时候一慌神 把段前缀给忘了
现改正如下:
assume cs:code
a segment
db 1,2,3,4,5,6,7,8
a end
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,b
mov es,ax
mov ax,c
mov ss,ax
mov bx,0
mov cx,8
s:mov al,[bx]
mov ah,es:[bx]
add al,ah
mov ss:[bx],al
inc bx
loop s
code ends
end start | | |
|
|
|
|
[第5楼]
[ 回复时间:2011-11-25 17:28 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:13
注册日期:2011-07-13 08:38 |
第(2)题有疑问,debug加载后cx中的值为42h,此值为程序的长度,该长度减去前面2个段(data和stack)的长度为20h后,剩下的22h应为code的有效长度,所以你说的code的长度为20h可能有误,因为ip=20h指出的是当前代码的位置,并没有把代码的全部长度指出,因此code段的长度应为30h。 | | |
|
|
|
|
[第6楼]
[ 回复时间:2011-11-25 17:33 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:13
注册日期:2011-07-13 08:38 |
用u命令查看对应的机器码也可以发现未到int 21h时就有20h字节了,加上int 21h肯定超过20h了:
-u
0B72:0000 B8710B MOV AX,0B71
0B72:0003 8ED0 MOV SS,AX
0B72:0005 BC1000 MOV SP,0010
0B72:0008 B8700B MOV AX,0B70
0B72:000B 8ED8 MOV DS,AX
0B72:000D FF360000 PUSH [0000]
0B72:0011 FF360200 PUSH [0002]
0B72:0015 8F060200 POP [0002]
0B72:0019 8F060000 POP [0000]
0B72:001D B8004C MOV AX,4C00 | | |
|
|
|
|
[第7楼]
[ 回复时间:2011-11-26 09:59 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:13
注册日期:2011-07-13 08:38 |
楼主第3题的答案也似乎有误:
②CPU执行程序,程序返回前,cs=14d3(此处应该是13d3)、ss=13d7、ds=13d6。
③设程序加载后,code段的段地址为X,则data段的段地址为X+2(此处应该是X+3),stack段的段地址为X+3(此处应该是X+4)。
在我的电脑上实验下来cs=0c97,ss=0c9b,ds=0c9a,所以ds=cs(0c97)+3=ds,ss=cs(0c97)+4=ss。
以上答案请指正。 | | |
|
|
|
|
[第8楼]
[ 回复时间:2011-11-27 18:18 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2011-10-05 19:31 |
|
|
|
|
|
[第9楼]
[ 回复时间:2011-11-27 18:18 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2011-10-05 19:31 |
回复:[第7楼]
------------------
嗯 确实有误 谢谢提醒 手动打的 还就错了 | | |
|