[Hb-XIII] 编写、应用中断例程

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


1 显示字符串

(1) 问题

编写安装int 7ch中断例程,功能为显示一个用0结束的字符串,中断例程安装在0:200处。


参数:(dh) = 行号,(dl) = 列号,(cl) = 颜色,ds:si指向字符串首地址。


以上中断例程安装成功后,对下面的程序进行单步跟踪,尤其注意观察int、iret指令执行前后CS、IP和栈中的状态。

Table 1. l131t.asm

1.       assume  cs:code

2.        

3.       data       segment

4.              db   "welcome to masm! ", 0

5.       data       ends

6.        

7.       code      segment

8.       start:      mov       dh,10

9.              mov       dl,10

10.          mov       cl,2

11.          mov       ax,data

12.          mov       ds,ax

13.          mov       si,0

14.          int   7ch

15.         

16.          mov       ax,4c00h

17.          int   21h

18.   code      ends

19.    end       start


(2) 安装代码

编写符合显示字符串的中断例程,只需要将课程设计I中显示字符串的show_str子函数(call – retf换成int - iret)安装到0:200处,再设置中断向量表即可。

1.        assume    cs:codesg

2.         

3.         

4.        codesg     segment

5.        start:

6.                 mov ax, cs

7.                 mov ds, axg

8.                 mov si, offset show_str  ;用ds:[si]指向需要被复制的程序

9.                

10.             mov ax, 0

11.             mov es, ax

12.             mov di, 200h                      ;中断例程内存段

13.            

14.             mov cx, offset str_e - offset show_str

15.             cld

16.             rep   movsb                         ;使用串传送指令,从ds:[si]传送cx字节到es:[di]

17.            

18.             mov ax, 0

19.             mov es, ax

20.             mov word ptr es:[7ch *4], 200h

21.             mov word ptr es:[7ch *4 + 2], 0

22.             ;设置中断向量表,N号中断的中断程序入口地址保存在(N * 4 + 2):(N * 4)内存中

23.            

24.             nop

25.             mov ax, 4c00h

26.             int    21h

27.            

28.             ;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串

29.             ;参数:(dh) = 行号(取值范围 0 ~ 24),(dl) = 列号(取值范围0 ~ 79),(cl) = 颜色,ds:si指向字符串的首地址

30.             ;返回:无

31.             show_str:

32.                       push          ax

33.                       push          cx

34.                       push          dx

35.                       push          es

36.                       push          bp

37.                       push          di

38.                       push          si

39.                      

40.                       mov ax, 0b800h

41.                       mov es, ax        ;es段保存显存段地址

42.                      

43.                       mov al, cl ;字符前景色保存到al

44.                      

45.                       mov bp, 0

46.                       mov ch, 0

47.                       mov cl, dh

48.                       inc    cl

49.                       str_s0:

50.                                jcxz  str_s1

51.                                add  bp,160              ;行号对应的显存地址

52.                                loop str_s0

53.                       str_s1:

54.                                mov di,0

55.                                mov ch,0

56.                                mov cl,dl

57.                       str_s2:    

58.                                jcxz  str_s3

59.                                add  di,2           ;列号对应的显存地址

60.                                loop str_s2                ;es:[di + bp]为dh行dl列对应的显存地址

61.                               

62.                       str_s3:    

63.                                mov cl,ds:[si]

64.                                jcxz  str_s4                ;检测当前字符是否为0,如果为0则转移到s4处执行

65.                                mov         es:[bp+ di],cl

66.                                inc    di

67.                                mov         es:[bp+di], al           ;字符前景色

68.                                inc    di

69.                                inc    si

70.                                loop str_s3

71.                                        

72.                       str_s4:    

73.                                pop  si

74.                                pop  di

75.                                pop  bp

76.                                pop  es

77.                                pop  dx

78.                                pop  cx

79.                                pop  ax

80.             iret

81.             str_e:       nop

82.    codesg     ends

83.    end  start


(3) 调试

将l131t.asm和l131i.asm分别编译连接为l131t.exe和l131i.exe,因为0:200 ~ 0:3FF内存操作系统不会占用(回收),所以运行l131i.exe程序后,显示字符串的程序依然在内存中,此时再运行l131t.exe可得如下结果:

Figure1. 运行结果
跟踪l131t.exe调试的结果:

Figure2. int 指令执行前后CS、IP和栈的变化
7202为标记寄存器的压栈内容,076C为CS压栈值,0010为IP压栈值,IP指向int指令的下一条指令。


Figure3. iret执行前后CS、IP和栈的变化

2 完成loop指令功能

(1) 问题

编写并安装int 7ch中断例程,功能为完成loop指令的功能。


参数:(cx) = 循环次数,(bx) = 位移。


以上中断例程安装成功后,对下面的程序进行单步跟踪,尤其注意观察int、iret指令执行前后CS、IP和栈中的状态。


在屏幕中间显示80个“!”。

Table3. l132t.asm

1.        assume    cs:code

2.         

3.        code          se gment

4.        start:        mov ax, 0b800h

5.                 mov es, ax

6.                 mov di, 160 * 12

7.                 mov bx, offset s -offset se

8.                 mov cx, 80

9.                 s:

10.                       mov         byteptr es:[di], '!'

11.                       add  di, 2

12.                       int    7ch

13.             se:    nop

14.            

15.             mov ax, 4c00h

16.             int    21h

17.    code        ends

18.    end         start


(2) 安装代码

Table4. l132i.asm

1.        assume    cs:codesg

2.         

3.         

4.        codesg     segment

5.        start:

6.                 mov ax, cs

7.                 mov ds, ax

8.                 mov si, offset lp       ;用ds:[si]指向需要被复制的程序

9.                

10.             mov ax, 0

11.             mov es, ax

12.             mov di, 200h                      ;中断例程内存段

13.            

14.             mov cx, offset lp_e -offset lp

15.             cld

16.             rep   movsb                         ;使用串传送指令,从ds:[si]传送cx字节到es:[di]

17.            

18.             mov ax, 0

19.             mov es, ax

20.             mov word ptr es:[7ch *4], 200h

21.             mov word ptr es:[7ch *4 + 2], 0

22.             ;设置中断向量表,N号中断的中断程序入口地址保存在(N * 4 + 2):(N * 4)内存中

23.            

24.             nop

25.             mov ax, 4c00h

26.             int    21h

27.            

28.             ;功能:实现loop的功能

29.             ;参数:(cx) = 循环次数,(bx) = 位移

30.             ;返回:无

31.             lp:

32.                       push          bp

33.                       mov bp, sp

34.                       dec   cx

35.                       jcxz  lpret

36.                       add  [bp +2], bx

37.                       lpret:        pop  bp

38.             iret

39.            

40.             lp_e:         nop

41.    codesg     ends

42.    end         start

(3) 调试

Figure4. 实现loop指令中断例程运行结果

int、iret执行前后CS、IP和栈内容变化与1相似。


3 补全程序,显示英文诗

(1) 问题

下面的程序,分别在屏幕的2、4、6、8行显示4句英文诗,补全程序。完成编译运行后,体会其中的编程思想。

1.        assume    cs:codesg

2.         

3.        codesg     segment

4.        s1:    db     'Good, better, best,', '$'

5.        s2:    db     'Never let it rest,', '$'

6.        s3:    db     'Till good is better,', '$'

7.        s4:    db     'And better, best. ','$'

8.        s:      dw    offset s1, offsets2, offset s3, offset s4

9.        row: db     2, 4, 6, 8

10.     

11.    start:

12.             mov ax, cs

13.             mov ds, ax

14.             mov bx, offset s

15.             mov si, offset row

16.             mov cx, 4

17.            

18.             ok:

19.                       mov bh, 0

20.                       mov dh, ds:[si]

21.                       mov dl, 0

22.                       mov ah, 2

23.                       int    10h  ;置光标

24.                      

25.                       mov dx,ds:[bx]

26.                       mov ah, 9

27.                       int    21h  ;显示以ds:[dx]首地址以'$'结尾的字符串

28.                      

29.                      inc    si

30.                       add  bx, 2

31.             loop ok

32.                      

33.             mov ax, 4c00h

34.             int    21h

35.    codesg     ends

36.    end         start

绿色下划线处为填补的程序。将多个字符串的地址组织在一块,通过寻址其地址来显示实现C中数组一样的功能。


(3) 调试

回车一片后再运行经编译和连接的程序,结果如下:


Figure5. 运行结果

此时光标在红色方框内,不用检查自己是否写了死循环程序。


[2014.12.20 - 17:57]
R《Hb》Note Over.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值