汇编网首页登录博客注册
towersimper的学习博客
博客首页博客互动【做检测题】论坛求助

我的博客

个人首页 |  我的文章 |  我的相册 |  我的好友 |  最新访客 |  文章收藏 |  论坛提问 |  友情链接 |  给我留言  
图片载入中
学习动态
最新留言

[2008-07-12 16:54] 第六章实验内容解答,提出新观点和新解法,望大家指教。

(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
   
a.CPU执行程序,程序返回前,data段的内容是多少?
    无需debug调试, push ds:[0],push ds:[2]后,[2]在栈顶,经过
pop ds:[2],pop ds:[0],栈顶先出栈,所以程序数据段依然没有变化。所以程序返回前,data中的数据为:
0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H

b.CPU执行程序,程序返回前,cs=____,ss=______,ds=______
    尽管可以用code,stack,data之类的标号来赋值,如cs=code,ss=stack,ds=data。不过,不同机器加载程序后,-t测试完后,会有具体的cs,ss和ds数值。我这边测试结果为cs=13F8,ss=13F7,ds=13F6

c.设程序加载后,code段的段地址为X,则data段的段地址为___,stack段的段地址为___。
  根据第二小问得出的计算结果为,data=X-2,stack=X-1。但如果根据下面的理解得到结果,或许更好,即:
C:\masm>debug p61.exe
-r
AX=0000  BX=0000  CX=0042  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=13E6  ES=13E6  SS=13F6  CS=13F8  IP=0000   NV UP EI PL NZ NA PO NC
13F8:0000 B8F713        MOV     AX,13F7
-d 13e6:100
13E6:0100  23 01 56 04 89 07 BC 0A-EF 0D ED 0F BA 0C 87 09   #.V.............
13E6:0110  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
13E6:0120  B8 F7 13 8E D0 BC 10 00-B8 F6 13 8E D8 FF 36 00   ..............6.
13E6:0130  00 FF 36 02 00 8F 06 02-00 8F 06 00 00 B8 00 4C   ..6............L
13E6:0140  CD 21 00 00 00 00 F9 13-FB 0D 22 00 E6 13 02 32   .!........"....2
13E6:0150  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
13E6:0160  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
13E6:0170  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
-u
13F8:0000 B8F713        MOV     AX,13F7
13F8:0003 8ED0          MOV     SS,AX
13F8:0005 BC1000        MOV     SP,0010
13F8:0008 B8F613        MOV     AX,13F6
13F8:000B 8ED8          MOV     DS,AX
13F8:000D FF360000      PUSH    [0000]
13F8:0011 FF360200      PUSH    [0002]
13F8:0015 8F060200      POP     [0002]
13F8:0019 8F060000      POP     [0000]
13F8:001D B8004C        MOV     AX,4C00
-u
13F8:0020 CD21          INT     21
13F8:0022 0000          ADD     [BX+SI],AL
13F8:0024 0000          ADD     [BX+SI],AL
13F8:0026 F9            STC
13F8:0027 13FB          ADC     DI,BX
13F8:0029 0D2200        OR      AX,0022
13F8:002C E613          OUT     13,AL
13F8:002E 0232          ADD     DH,[BP+SI]
13F8:0030 0000          ADD     [BX+SI],AL
13F8:0032 0000          ADD     [BX+SI],AL
13F8:0034 0000          ADD     [BX+SI],AL
13F8:0036 0000          ADD     [BX+SI],AL
13F8:0038 0000          ADD     [BX+SI],AL
13F8:003A 0000          ADD     [BX+SI],AL
13F8:003C 0000          ADD     [BX+SI],AL
13F8:003E 0000          ADD     [BX+SI],AL
可知data段占据第一排(根据-d显示结果的方式,即每16个存储单元显示为一排),而data段共8个字型数据,故刚好占据一排空间,接下来就是stack段,也刚好占据一排,根据-u的结果可知,stack段下面一排存放的就是code代码段。因此可知,data段初始地址比code段小2排(即32个内存单元),stack的比code的小1排(即16个内存单元)。所以,
code*16+0-(data*16+0)=2*16,而code=X,所以,data=X-2,同理,stack=X-1。

(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

a.CPU执行程序,程序返回前,data段的内容是多少?
跟前面一样,data段的内容不便,依然为: 0123H,0456H

b.CPU执行程序,程序返回前,cs=____,ss=______,ds=______
还是可以用cs=code,ss=stack,ds=data表示。具体执行时,不同的机器得出额结果不一样,我的机器给出的是,cs=13F8,ss=13F7,ds=13F6

c.设程序加载后,code段的段地址为X,则data段的段地址为___,stack段的段地址为___。
根据上面额结果,可知data=X-2,stack=X-1。
也可以先用Debug加载p62.exe,再用-d和-u指令计算data和stack段的段地址,如题1一样。只不过,这里的data和stack段的数据所占空间为4个内存单元,不足一排,但仍要占据一排。所以结果跟题1一样。

d.对于如下定义的段:
  name segment
  ...
  name ends
如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为__。
    段中的数据占N个字节,意味着占N个存储单元,在debug调试中输入-t后,显示以16个存储单元为一排。因此,用N/16表示占有几排,如果商为零,表示不足一排,仍给它一排的空间,也可写成(N/16+1)*16,如题2中
data segment
     dw 0123H,0456H
data ends
stack segment
     dw 0,0
stack ends;
此外,题3中也是这样的。

如果商刚好为整数t,表明则就占据t排空间,则实际占有空间为(N/16)*16,如题1中,
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;
若商为t,还带有余数,表明t排空间不够,t+1排又填不满,不过仍让填不满空间的一排占有一排,所以为t+1排,则实际占有空间为(N/16+1)*16。其中(N/16)都只取商的整数部分,小数部分去掉。
因此,看了参考答案后,就写做(N/16+1)*16,恐怕不对吧。按照这个等式,像下面的段按照N/16+1)*16计算,应该占有(16/16+1)*16=32个存储单元,可是16个存储单元足以填充这些数据。
data segment
     dw 0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H
data ends
   那么用实验来证明,在用masm和link得到题1中的可执行文件(我这边的文件为p61.exe)后,进入cmd后,切换到c:\masm目录中。结果如下。
C:\masm>debug p61.exe
-r
AX=0000  BX=0000  CX=0042  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=13E6  ES=13E6  SS=13F6  CS=13F8  IP=0000   NV UP EI PL NZ NA PO NC
13F8:0000 B8F713        MOV     AX,13F7
-d 13e6:100
13E6:0100  23 01 56 04 89 07 BC 0A-EF 0D ED 0F BA 0C 87 09   #.V.............
13E6:0110  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
13E6:0120  B8 F7 13 8E D0 BC 10 00-B8 F6 13 8E D8 FF 36 00   ..............6.
13E6:0130  00 FF 36 02 00 8F 06 02-00 8F 06 00 00 B8 00 4C   ..6............L
13E6:0140  CD 21 00 00 00 00 00 00-00 00 00 00 00 00 00 00   .!..............
13E6:0150  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
13E6:0160  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
13E6:0170  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
其中第一排结果是data段占据的实际空间为,16个存储单元,此外,stack段也是如此,只占16个存储单元。

(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 0123H,0456H
data ends
stack segment
     dw 0,0
stack ends
end start

a.CPU执行程序,程序返回前,data段的内容是多少?
与前面一样,依然为0123H,0456H。

b.CPU执行程序,程序返回前,cs=____,ss=______,ds=______
还是可以用cs=code,ss=stack,ds=data表示。具体执行时,不同的机器得出额结果不一样,我的机器给出的是,cs=13F6,ss=13FA,ds=13F9

c.设程序加载后,code段的段地址为X,则data段的段地址为___,stack段的段地址为___。
C:\masm>debug p63.exe
-r
AX=0000  BX=0000  CX=0044  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=13E6  ES=13E6  SS=13F6  CS=13F6  IP=0000   NV UP EI PL NZ NA PO NC
13F6:0000 B8FA13        MOV     AX,13FA
-d 13E6:100
13E6:0100  B8 FA 13 8E D0 BC 10 00-B8 F9 13 8E D8 FF 36 00   ..............6.
13E6:0110  00 FF 36 02 00 8F 06 02-00 8F 06 00 00 B8 00 4C   ..6............L
13E6:0120  CD 21 00 00 00 00 00 00-00 00 00 00 00 00 00 00   .!..............
13E6:0130  23 01 56 04 00 00 00 00-00 00 00 00 00 00 00 00   #.V.............
13E6:0140  00 00 00 00 00 00 F9 13-FB 0D 22 00 E6 13 02 32   .........."....2
13E6:0150  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
13E6:0160  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
13E6:0170  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
-u 
13F6:0000 B8FA13        MOV     AX,13FA
13F6:0003 8ED0          MOV     SS,AX
13F6:0005 BC1000        MOV     SP,0010
13F6:0008 B8F913        MOV     AX,13F9
13F6:000B 8ED8          MOV     DS,AX
13F6:000D FF360000      PUSH    [0000]
13F6:0011 FF360200      PUSH    [0002]
13F6:0015 8F060200      POP     [0002]
13F6:0019 8F060000      POP     [0000]
13F6:001D B8004C        MOV     AX,4C00
-u
13F6:0020 CD21          INT     21
13F6:0022 0000          ADD     [BX+SI],AL
13F6:0024 0000          ADD     [BX+SI],AL
13F6:0026 0000          ADD     [BX+SI],AL
13F6:0028 0000          ADD     [BX+SI],AL
13F6:002A 0000          ADD     [BX+SI],AL
13F6:002C 0000          ADD     [BX+SI],AL
13F6:002E 0000          ADD     [BX+SI],AL
13F6:0030 2301          AND     AX,[BX+DI]
可知INT     21汇编指令对应的机器指令是位于13F6:0020的CD21。
根据-d 13E6:100显示的结果可知,代码段code占据3排,而且3排没有排满,因为第三排中只有最前面两个内存单元被使用,为CD 21即该段程序的最后一条指令的机器码。尽管没有排满,但仍要占据一排。跟在code段后面的是data,然后才是stack段。所以data的初始地址比代码段的初始地址要大3排,即(16×data+0)-(16×X+0)=3×16,所以
data=X+3。而data段只有2两个字型数据,占有4个内存单元,不足一排,根据公式,仍得占据一排,所以stack段的初始地址跟data段的相差一个一排,即16个内存单元。所以stack×16+0-data×16-0=16所以,stack=data+1=X+4。


(4)如果将1、2、3题中的最后一条伪指令"end start"改为"end"(也就是说,不指明程序的入口),则哪个程序仍然可以正确执行?请说明原因。
只有3题中可以正常运行。因为3题中,code段在最前面,cs:0直接指向code代码段,所以可以运行。而1和2题中,则是代码段放在最后,data段放在最前,所以cs:0指向data段,当然不会正确执行。

(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 ends

code segment
start:
    ?
code ends
end start
首先根据题1、2和3中的理解,a、b和c段存放的都是8个字节型数据,占据8个内存空间,不足一排,但仍要占据一排,且根据段排列的先后顺序可知,b段的段地址要比a段的大16,c段的段地址要比a的大32。即b=a+1,c=a+2。同时可以这样考虑,b段的段地址依然为a段的段地址,但是b段的偏移地址一律加上一个常数16,c段的段地址依然为a段的段地址,但是c段的偏移地址一律加上一个常数32。基于这种考虑据此,编写如下。
缺少的指令代码如下:
mov ax,a
mov ds,ax
mov bx,0
mov cx,8
s:mov dl,[bx]
  mov al,[bx+16]
  add al,dl
  mov [bx+32],al
  inc bx
loop s
mov ax,4c00H
int 21H

将上面的程序命名为p65.asm,经过编译连接后产生名为p65.exe的可执行文件。
C:\masm>debug p65.exe
-r
AX=0000  BX=0000  CX=004D  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=13E6  ES=13E6  SS=13F6  CS=13F9  IP=0000   NV UP EI PL NZ NA PO NC
13F9:0000 B8F613        MOV     AX,13F6

-d 13e6:100
13E6:0100  01 02 03 04 05 06 07 08-00 00 00 00 00 00 00 00   ................
13E6:0110  01 02 03 04 05 06 07 08-00 00 00 00 00 00 00 00   ................
13E6:0120  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................
13E6:0130  B8 F6 13 8E D8 BB 00 00-B9 08 00 8A 17 8A 47 10   ..............G.
13E6:0140  02 C2 88 47 20 43 E2 F3-B8 00 4C CD 21 C0 22 80   ...G C....L.!.".
13E6:0150  3E 45 07 00 74 0A FF 36-56 07 E8 21 FC 83 C4 02   >E..t..6V..!....
13E6:0160  FF 06 56 07 5E 8B E5 5D-C3 90 55 8B EC 81 EC 90   ..V.^..]..U.....
13E6:0170  00 56 C4 5E 06 26 8B 47-08 89 46 F8 26 83 7F 06   .V.^.&.G..F.&...

-u
13F9:0000 B8F613        MOV     AX,13F6
13F9:0003 8ED8          MOV     DS,AX
13F9:0005 BB0000        MOV     BX,0000
13F9:0008 B90800        MOV     CX,0008
13F9:000B 8A17          MOV     DL,[BX]
13F9:000D 8A4710        MOV     AL,[BX+10]
13F9:0010 02C2          ADD     AL,DL
13F9:0012 884720        MOV     [BX+20],AL
13F9:0015 43            INC     BX
13F9:0016 E2F3          LOOP    000B
13F9:0018 B8004C        MOV     AX,4C00
13F9:001B CD21          INT     21
13F9:001D C0            DB      C0
13F9:001E 22803E45      AND     AL,[BX+SI+453E]
-t

AX=13F6  BX=0000  CX=004D  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
DS=13E6  ES=13E6  SS=13F6  CS=13F9  IP=0003   NV UP EI PL NZ NA PO NC
13F9:0003 8ED8          MOV     DS,AX
-g 0018

AX=1310  BX=0008  CX=0000  DX=0008  SP=0000  BP=0000  SI=0000  DI=0000
DS=13F6  ES=13E6  SS=13F6  CS=13F9  IP=0018   NV UP EI PL NZ NA PO NC
13F9:0018 B8004C        MOV     AX,4C00
-t

AX=4C00  BX=0008  CX=0000  DX=0008  SP=0000  BP=0000  SI=0000  DI=0000
DS=13F6  ES=13E6  SS=13F6  CS=13F9  IP=001B   NV UP EI PL NZ NA PO NC
13F9:001B CD21          INT     21
-g

Program terminated normally

-d 13e6:100
13E6:0100  01 02 03 04 05 06 07 08-00 00 00 00 00 00 00 00   ................
13E6:0110  01 02 03 04 05 06 07 08-00 00 00 00 00 00 00 00   ................
13E6:0120  02 04 06 08 0A 0C 0E 10-00 00 00 00 00 00 00 00   ................
13E6:0130  B8 F6 13 8E D8 BB 00 00-B9 08 00 8A 17 8A 47 10   ..............G.
13E6:0140  02 C2 88 47 20 43 E2 F3-B8 00 4C CD 21 C0 22 80   ...G C....L.!.".
13E6:0150  3E 45 07 00 74 0A FF 36-56 07 E8 21 FC 83 C4 02   >E..t..6V..!....
13E6:0160  FF 06 56 07 5E 8B E5 5D-C3 90 55 8B EC 81 EC 90   ..V.^..]..U.....
13E6:0170  00 56 C4 5E 06 26 8B 47-08 89 46 F8 26 83 7F 06   .V.^.&.G..F.&...
发现,第三排为前两排数之和。说明该编程有效。好开心啊。呵呵。

(6)程序如下,编写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
逆序排列,用入栈和出栈编程,再好不过的了。同时也根据题1、2和3的理解,不用两次为数据段a和b设置ds段地址,因为a段中的数据大小为16个字节,刚好占据一排,b中也如此,也是占据一排,根据先后顺序,可知,b段中的段地址要比a中的大一排(即16个存储单元),即b=a+1。同时可以这样考虑,b段的段地址依然为a段的段地址,但是b段的偏移地址一律加上一个常数16。基于这种考虑,则缺失的代码为
mov ax,a
mov ds,ax
mov ss,b
mov sp,20H
mov bx,0
mov cx,8
s:push [bx]
  add bx,2
loop s
mov ax,4c00H
int 21H
评论次数(10)  |  浏览次数(1719)  |  类型(汇编作业) |  收藏此文  | 

[  tomato   发表于  2008-07-13 11:21  ]

博主的答案都挺正确!原来这个习题可以分析出这么丰富的内容。
只是有一点想的不同的地方,就是第五题中,博主为何用16位的dx相加,8位的不更节省指令?

[  towersimper   发表于  2008-07-13 17:01  ]

mov ax,dx指令也应改为mov al,dl。刚开始编写的时候,没有大注意,就贴了出来,后来自己也发现了,只是忘记将帖子中的内容更正过来。多谢tomato的提醒。已经更改过来了。

[  ym3823078   发表于  2008-07-18 17:47  ]

请 问 一下第一 问,您 为什么用-d 13e6:100,而不 用
 -d 13e6:0

[  towersimper   发表于  2008-07-19 09:39  ]

应为cmd在加载exe可执行文件时,ds:0-ds:FF为PSP数据前缀区,其后才是程序的内容。ds:0-ds:FF所在的内容给实验结果无关,所以就忽略了。我想你或许已忘记了相关内容,所以最好再回顾一下。

[  游客   发表于  2008-07-19 10:39  ]

非常的感谢,回答的非常的 好!

[  ym3823078   发表于  2008-07-19 10:45  ]

这位兄弟,发现你上面回答一 针见血,劳烦你 帮 我 看下 这个问题,不 知道 你 遇上过没?谢谢http://www.asmedu.net/bbs/pasteinfo.jsp?part=1&level=book&kind=1004&qkSg=2&qID=20101&readSg=1

[  sbx2000_0   发表于  2008-07-23 23:27  ]

做的好,即清晰,又准确!

[  游客   发表于  2008-10-08 11:35  ]

兄弟,(6)中为什么用2个inc bx呢,用add bx,2不可以吗

[  sexion   发表于  2008-10-08 11:57  ]

mov ss,b。。。。。错了吧

[  towersimper   发表于  2010-07-16 23:48  ]

当然可以用add bx,2代替啊。

 
 请输入验证码  (提示:点击验证码输入框,以获取验证码