[Hb-V] 编写 调试具有多个段的程序

《汇编语言·第三版》--王爽


1 各段段地址连续分配

将下面的程序编译、连接,用debug加载、跟踪,然后回答问题。

Table1. l51.asm

1.         assume    cs:code, ds:data, ss:stack

2.          

3.         data segment

4.                  dw    0123h, 0456h, 0789h, 0abch, 0defh, 0fedfh, 0cbah, 0987h

5.         data ends

6.          

7.          

8.         stack         segment

9.                  dw    0, 0, 0, 0, 0, 0, 0, 0

10.     stack         ends

11.      

12.      

13.     code          segment

14.     start:

15.              mov ax, stack

16.              mov ss, ax

17.              mov sp, 16

18.             

19.              mov ax, data

20.              mov ds, ax

21.             

22.              push          ds:[0]

23.              push          ds:[2]

24.              pop  ds:[2]

25.              pop  ds:[0]

26.             

27.              mov ax, 4c00h

28.              int    21h

29.     code          ends

30.      

31.     end  start


Figure1. l51.asm调试结果

(1) CPU执行程序,程序返回前,data段中的数据不变。

(2) CPU执行程序,程序返回前,cs =076CH、ss =076B、ds = 076A。这些值需要调试观看。

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


各段地址相差16的整数倍,最多相差2^16字节(64kb)


2 段实际所占内存大小

将下面的程序编译、连接,用debug加载、跟踪,然后回答问题。

Table 2. l152.asm

1.         assume    cs:code, ds:data, ss:stack

2.          

3.         data segment

4.                  dw    0123H, 0456H

5.         data ends

6.          

7.          

8.         stack         segment

9.                  dw    0, 0

10.     stack         ends

11.      

12.      

13.     code          segment

14.     start:        mov ax, stack

15.              mov ss, ax

16.              mov sp, 16

17.             

18.              mov ax, data

19.              mov ds, ax

20.             

21.              push          ds:[0]

22.              push          ds:[2]

23.              pop  ds:[2]

24.              pop  ds:[0]

25.             

26.              mov ax, 4c00h

27.              int    21h

28.     code          ends

29.      

30.     end  start


Figure2. 152.asm调试结果

(1) CPU执行程序,程序返回前,data段中的数据不变。

(2) CPU执行程序,程序返回前,cs =076CH、ss =076B、ds =076A。这些值需要调试观看。

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


相邻的两个段相差16个单元,程序将数据写到了stack:14和stack:12两个地址处:


Figure3. stack:14和stack:12处被写入的内容


运行到把data段的数据压倒栈中的地方,此时stack:14和stack:12处显示压入的值。单步运行:

Figure4. 出栈后 栈的值

每当执行一个pop指令后,出栈后的内存单元内的数据就发生了变化,它不保证经出栈后的内存单元的值还保持原值。


(4) 对于如下定义的段:

段名        segment

段名        ends

如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为N字节(N为16的正整数倍),(N/16 + 1) * 16(N/16取商的整数部分,如17/16 = 1)字节(不超过64KB)

3 段地址根据其定义先后分配

将下面的程序编译、连接,用debug加载、跟踪,然后回答问题。

Table 3. l53.asm

1.         assume    cs:code, ds:data, ss:stack

2.          

3.         code          segment

4.         start:        mov ax, stack

5.                  mov ss, ax

6.                  mov sp, 16

7.                 

8.                  mov ax, data

9.                  mov ds, ax

10.             

11.              push          ds:[0]

12.              push          ds:[2]

13.              pop  ds:[2]

14.              pop  ds:[0]

15.             

16.              mov ax, 4c00h

17.              int    21h

18.     code          ends

19.      

20.      

21.     data segment

22.              dw    0123h, 0456h

23.     data ends

24.      

25.      

26.     stack         segment

27.              dw    0, 0

28.     stack         ends

29.      

30.     end  start



Figure5. 各段地址

(1) CPU执行程序,程序返回前,data段中的数据不变。

(2) CPU执行程序,程序返回前,cs =076AH、ss =076E、ds =076D。这些值需要调试观看。

(3) 设程序加载后,code段的段地址为X,则data段的段地址为X+3,stack段的段地址为X+4


4 汇编程序的入口地址

如果将1、2、3题中的最后一条伪指令“end start”改为“end”(也就是说,不指明程序的入口),则哪个程序仍然可以正确执行?请说明原因。


答:不包含“start”标号和“end start”伪指令的汇编程序会默认写在最前面的汇编程序为程序入口。去掉l51.asm汇编程序“end start”中的“start”后用u命令查看汇编指令,发现跟汇编程序不再对应:


Figure6. 无start end语句的汇编程序

这些莫名的指令都来源于data段的数据。

所以,去掉“start”后,3中的汇编程序可以正常运行。


5 两段数据段数据相加到第三个数据段中

(1) 补写代码段

Table 4. l55.asm

1.         assume    cs:code

2.          

3.         a       segment

4.                  db     1, 2, 3, 4, 5, 6, 7, 8

5.         a       ends

6.          

7.          

8.         b       segment

9.                  db     1, 2, 3, 4, 5, 6, 7, 8

10.     b       ends

11.      

12.      

13.     c       segment

14.              db     0, 0, 0, 0, 0, 0, 0, 0

15.     c       ends

16.      

17.      

18.     code          segment

19.     start:       mov ax, a

20.              mov ds, ax

21.              mov ax, b

22.              mov es, ax        ;es作为b数据段段地址

23.              mov ax, c

24.              mov ss, ax        ;ss作为c数据段段地址

25.             

26.              mov bx, 0

27.              mov cx, 8

28.     s:      mov al, [bx]

29.              add  al, es:[bx]

30.              mov ss:[bx], al

31.              inc    bx

32.              loop s

33.             

34.              mov ax, 4c00h

35.              int    21h

36.     code          ends

37.     end  start


(2) 查看结果

用masm编译连接以上程序生成l55.exe。用debug加载l55.exe,首先用u命令查到c数据段的段地址076CH,然后找到“int 21h”地址,运行至“int 21h”处后用d 076c:0 8命令查看c数据段内容是否对应为a,b两数据段数据对应相加的值。

Figure7. 调试c数据段内存中的值

6 用栈将一数据段的内容拷贝至另外一个段中

(1) 编写的代码段

Table 5. l156.asm

1.         assume    cs:code

2.          

3.         a       segment

4.                  dw    1, 2, 3, 4, 5, 6, 7, 8, 9, 0ah, 0bh, 0ch, 0dh, 0eh, 0fh, 0ffh

5.         a       ends

6.          

7.          

8.         b       segment

9.                  dw    0, 0, 0, 0, 0, 0, 0, 0

10.     b       ends

11.      

12.      

13.     code          segment

14.     start:        mov ax, a

15.              mov ds, ax

16.             

17.              mov ax, b

18.              mov ss, ax

19.              mov sp, 16

20.      

21.              mov bx, 0

22.              mov cx, 8

23.     s:      push          [bx]

24.              inc    bx

25.              inc    bx

26.              loop s

27.             

28.              mov ax, 4c00h

29.              int    21h

30.     code        ends

31.     end  start


(2) 查看结果


Figure8. 查看数据段内存中的值
001c为“int 21h”偏移地址。076c为b段段地址。

7 总结

汇编源程序中,用“end start”说明程序的入口地址为“start”处,这个入口地址将被写入可执行文件的描述信息,可执行文件被加载入内存后,CPU的CS:IP被设置指向这个入口地址,从而开始执行程序中的第一条指令。标号“start”在“code”段中,这样CPU段中的内容就被当作指令来执行了。再在代码段中设置ss指向某段,那么这段就可以被当成栈来使用(使用push, pop指令时,ss和sp两个寄存器会自动配合),数据段同理。CPU是如何处理我们定义的段中的内容,是当作指令执行,还是当作数据访问,还是当作栈空间,完全依靠程序中的汇编指令,和汇编指令对CS:IP、SS:SP、DS等寄存器的设置决定的。


汇编源程序中的段被加载到内存中时,以(16)字节对齐的方式连续存储。


[2014.11.24 - 1:51]
R《Hb》Note Over.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值