回 帖 发 新 帖 刷新版面

主题:急问用汇编怎样编写时钟SOS!!!!

哥哥们,帮帮小弟吧!小弟又有题目不会写了!!谢谢了!!


编写 MYINT1C.ASM
功能:
    实现 INT 1C
    MY INT 1C 实现的功能在屏幕的右上角显示秒表或时钟(秒表简单,时钟有加分)
    按ESC,退出程序。

有关技术方法说明:

[替换中断的方法有两种]:
==============================================================================
方法1[推荐]:直接对中断向量表操作

MY_INTNO    DW      1CH
OLD_INTOFF    DW    ?
OLD_INTSEG    DW    ?

; ------ 替换中断方法
                MOV     AX,MY_INTNO
                SHL    AX, 2
                MOV    DI, AX
                MOV    AX, 0
                MOV    ES, AX        ;此时,ES:DI是中断向量的地址

                CLI            ;禁止中断
                MOV     AX, ES:[DI]
                MOV    OLD_INTOFF,AX
                MOV    AX,OFFSET MY_INT1C
                MOV    ES:[DI]

                MOV    AX,ES:[DI+2]
                MOV    OLD_INTSEG, AX
                MOV    AX, CS
                MOV    ES:[DI+2], AX
                STI            ;允许中断

                ...

; ------ 退出前恢复原中断的方法
                MOV     AX,MY_INTNO
                SHL    AX, 2
                MOV    DI, AX
                MOV    AX, 0
                MOV    ES, AX        ;此时,ES:DI是中断向量的地址

                CLI            ;禁止中断
                MOV     AX, OLD_INTOFF
                MOV    ES:[DI], AX
                ADD    DI,2
                MOV     AX, OLD_INTSEG
                MOV    ES:[DI], AX
                STI            ;允许中断




; ------ 我们的中断处理程序
MY_INT1C    PROC
        ...
        IRET
MY_INT1C    ENDP

==============================================================================
方法2:使用DOS 功能

35    取中断向量    INPUT:AL=中断类型    OUTBUP:ES:BX=中断向量
25    设置中断向量    INPUT:DS:DX=中断向量  AL=中断类型号

先取中断向量保存,设置自己的中断向量,等ESC KEY,设置原来的中断向量,退出

[显示的方法有两种]:
==============================================================================
方法1[推荐]:直接对中断向量表操作
        
    MOV    AX, 0B800H    ; TEXT 页面内存地址
    MOV    ES, AX
    MOV    DI, 71*2    ; 第1行,第72列;  (按行排列,第1行,1-80列,第2行,1-80列 ...)
    
    ...
    MOV    ES:[DI], AX    ; AL, 你想显示的字, AH,显示属性                               

==============================================================================
方法2: 使用BIOS功能
10    2    置光标位置            BH=页号   DH,DL=行,列
10     9     在光标位置显示字符及属性     BH=显示页 AL=字符 BL=属性 CX=字符重复次数
10    A    在光标位置显示字符            BH=显示页 AL=字符 CX=字符重复次数
10    E    显示字符(光标前移)            AL=字符 BL=前景色     

==============================================================================
关于显示属性:

1个BYTE,高4位为背景属性,低4位为前景属性(字符)

4位含义     . . . .
     | | | |
     | | | +--------------------兰色
     | | +----------------------绿色
     | +------------------------红色
     +--------------------------亮度

回复列表 (共3个回复)

沙发

int 1ch不适合做时钟(可以做秒表),int 1ch是8253/8254定时器0的int 9h中断服务程序调用的,默认情况下(机器启动经BIOS设置后)每隔55ms产生一次int 09h中断,因为中断勾子踩正点勾连的机会只有百万分之一,因此这样做出来的时钟总会有一个误差,除非你不在乎这个误差,否则应该用int 4Ah做这个时钟。int 1Ah时钟管理的6号功能能够设置一个闹钟,闹钟一到点就会调用int 4ah,应该在4ah上装一个勾子,设置一个一秒钟的闹钟,就是每隔一秒显示一下时间,这样的时钟比1ch精确得多,与机器基本同步。

你的问题偶前几天在C/C++版回答过,用C写了一个时钟,虽然是高级语言,但整个过程其实是汇编,只不过用了高级语言来描述。如果你看不懂C,希望用汇编的话,我可以给你改一个汇编的,但得等我做完今天的工作,那最早都可能是晚上或者明天了。

板凳

timer函数有两句内联汇编,是用来维护中断链的,由于tc没有提供操作堆栈的函数,只有用汇编了。如果你不懂如何编译内联汇编,可以把那两句去掉,作为例子,去掉它基本没有问题,除非要做TSR。

按任意键退出。

#pragma inline

#include <stdio.h>
#include <dos.h>
#include <conio.h>

void interrupt (*GFp_Vector)();
void interrupt timer();
void inittimer(unsigned char, unsigned char, unsigned char);


int main(void)
{
    unsigned char    uc_Hours, uc_Minutes, uc_Seconds;

    _AH = 2;
    geninterrupt(0x1a);
    uc_Hours = _CH;
    uc_Minutes = _CL;
    uc_Seconds = _DH;
    inittimer(uc_Hours, uc_Minutes, uc_Seconds);
    clrscr();
    GFp_Vector = getvect(0x4a);
    disable();
    setvect(0x4a, timer);
    enable();
    while (1) {
        if (kbhit()) break;
    }
    disable();
    setvect(0x4a, GFp_Vector);
    enable();
    return 0;
}

void inittimer(unsigned char uc_Hours, 
               unsigned char uc_Minutes, 
               unsigned char uc_Seconds)
{
    ++uc_Seconds;
    if ((uc_Seconds & 0x0f) >= 10) {
        uc_Seconds = uc_Seconds + 0x10 & 0xf0;
        if (uc_Seconds >= 0x60) {
            uc_Seconds = 0;
            ++uc_Minutes;
            if ((uc_Minutes & 0x0f) >= 10) {
                uc_Minutes = uc_Minutes + 0x10 & 0xf0;
                if (uc_Minutes >= 0x60) {
                    uc_Minutes = 0;
                    ++uc_Hours;
                    if ((uc_Hours & 0x0f) >= 10) {
                        uc_Hours = uc_Hours + 0x10 & 0xf0;
                        if (uc_Hours >= 0x24) {
                            uc_Hours = 0;
                        }
                    }
                }
            }
        }
    }
    _AH = 7;
    geninterrupt(0x1a);
    _CH = uc_Hours;
    _CL = uc_Minutes;
    _DH = uc_Seconds;
    _AH = 6;
    geninterrupt(0x1a);
    return;
}

void interrupt timer()
{
    unsigned char    uc_Hours, uc_Minutes, uc_Seconds;
    unsigned char    uc_TimeStr[8];
    int             i;

    asm pushf
    asm call dword ptr GFp_Vector
    _AH = 2;
    geninterrupt(0x1a);
    uc_Hours = _CH;
    uc_Minutes = _CL;
    uc_Seconds = _DH;
    uc_TimeStr[0] = (uc_Hours >> 4) + '0';
    uc_TimeStr[1] = (uc_Hours & 0x0f) + '0';
    uc_TimeStr[2] = ':';
    uc_TimeStr[3] = (uc_Minutes >> 4) + '0';
    uc_TimeStr[4] = (uc_Minutes & 0x0f) + '0';
    uc_TimeStr[5] = ':';
    uc_TimeStr[6] = (uc_Seconds >> 4) + '0';
    uc_TimeStr[7] = (uc_Seconds & 0x0f) + '0';
    _AH = 2;
    _BH = 0;
    _DH = 11;
    _DL = 36;
    geninterrupt(0x10);
    for (i = 0; i <= 7; ++i) {
        _AH = 0x0e;
        _BH = 0;
        _AL = uc_TimeStr[i];
        geninterrupt(0x10);
    }
    inittimer(uc_Hours, uc_Minutes, uc_Seconds);
    return;
}

3 楼

如果要汇编写的话,找一下这本书<汇编语言课程设计案例精编>,中国水利水电出版社

我来回复

您尚未登录,请登录后再回复。点此登录或注册