• 汇编(五)


      用汇编实现这样一个计时器,正计时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

     

     

     

     

     

  • 相关阅读:
    查看变量是否删除在鼠标工具中用到了。
    poly 顶点坐标的函数
    out/target/product/generic/obj/EXECUTABLES/BufferQueue_test_intermediates/LINKED/BufferQueue_test] Error 1
    undefined reference to `pthread_mutexattr_destroy'
    [out/host/linuxx86/obj/STATIC_LIBRARIES/libutils_intermediates/RefBase.o] Error 1
    can't find a register in class `GENERAL_REGS' while reloading `asm'
    error: ‘ptrdiff_t’ does not name a type
    armeabi4.4.3 引起的错误
    error: "_FORTIFY_SOURCE" redefined [Werror]
    :0:0: 错误: “_FORTIFY_SOURCE”重定义 [Werror]
  • 原文地址:https://www.cnblogs.com/xiongmao-cpp/p/4926059.html
Copyright © 2020-2023  润新知