汇编(五)
用汇编实现这样一个计时器,正计时60s后退出,要求屏幕显示0-59的秒数。安a键后,保留旧时间,重新另起一行开始计时。
要实现这样一个功能,需要用到这样几个调用。1CH、35H、25H、08H,同时还要熟悉汇编中如何编写中断程序。
1CH:该中断没55s由系统调用一次,每秒大概调用18次(非精确数字),我们就是要通过修改这个中断的入口地址,将其指向新中断,从而实现计时。
35H:INT 21H的获取中断向量功能。AH=35H。入口参数:AL=中断向量号。出口参数:ES:BX=中断服务程序的入口地址(段基地址:偏移地址)。例如,执行mov ax,351ch int 21H后,将获得1CH的中断程序入口地址,保存在ES和BX寄存器中。
25H:INT21H的设置中断向量功能。AH=25H。入口参数:AL=中断向量号;DS:DX中断服务程序入口地址(段基地址:偏移地址)。例如,执行mov ax,251CH int 21H后,将使得1CH中断的入口地址变为DS:DX(需事先将入口地址保存到相应的寄存器中)。
08H:从键盘读一字符但不回显,此功能调用检查字符是否是Ctrl-Break。
汇编中的中断编写大致步骤:保存原中断入口地址(35H)->设置新中断入口地址(25H)->执行新中断处理->调用原中断(call指令)->恢复原中断入口地址(25H)
被程序的实现流程图如下所示:
汇编代码实现如下所示:
;汇编实现计时器 stack segment stack db 2014 dup(?) stack ends data segment old1c dw ?,? clock db 0 flag db 0 time dw 0 keyFlag db 0 data ends code segment 'code' assume cs:code,ds:data,ss:stack start: mov ax,data mov ds,ax mov al,1CH mov ah,35H int 21H mov old1c[0],bx mov ax,es mov old1c[2],ax push ds mov dx,offset int1c mov ax,seg int1c mov ds,ax mov al,1CH mov ah,25H int 21H pop ds again: cmp flag ,1 jz done jmp again done: push ds mov dx,old1c[0] mov ax,old1c[2] mov ds,ax mov al,1cH mov ah,25H int 21H pop ds mov ax,4c00H int 21H int1c proc far push dx push ax sti mov ax,data mov ds,ax add clock,1 CMP clock, 1000/55 ;计数器每达到18时秒数加1 jl finish mov clock,0 ;显示时间 mov dl,0dH mov ah,02H int 21H mov ax,time mov dl,10 div dl mov dl,al mov dh,ah mov ah,02H add dl,30H int 21H mov ah,02H mov dl,dh add dl,30H int 21H inc time cmp time,60 ;判断是否达到60s jl finish mov flag,1 jmp finish2 finish: ;判断键盘是否按下? mov al,0 mov ah,0BH int 21H or al,0 jnz other jmp finish2 other: mov ah,08H ;清除键盘缓冲区 int 21H mov ah,02H mov dl,0dH int 21H mov dl,0ah int 21H mov time,0 ;重置计时数据 mov clock,0 finish2: PUSHF call dword ptr old1c cli pop ax pop dx iret int1c endp code ends end start
——来自 熊猫 [http://www.cnblogs.com/xiongmao-cpp/]