RTC和周期性中断

时间:2012-01-19 21:54:11

标签: assembly timer x86 device

有人能告诉我如何让RTC产生周期性中断吗?这是我试过的。

mov al, 0Bh
out 70h, al
in al, 71h
or al, 10000000b
push ax
mov al, 0Bh
out 70h, al
pop ax
out 71h, al

mov al, 0Ah
out 70h, al
in al, 71h
or al, 00001111b
push ax
mov al, 0Ah
out 70h, al
pop ax
out 71h, al

mov al, 0Bh
out 70h, al
in al, 71h
or al, 01000000b
push ax
mov al, 0Bh
out 70h, al
pop ax
out 71h, al

mov al, 0Bh
out 70h, al
in al, 71h
and al, 01111111b
push ax
mov al, 0Bh
out 70h, al
pop ax
out 71h, al

我做错了什么?在我看来,阻止RTC并不是很重要,但这是我可以尝试的最后一件事。

1 个答案:

答案 0 :(得分:0)

我在Borland / Turbo Pascal中有一些旧代码,它曾经在真正的硬件上工作,仍然可以在DosBox中运行,看看是否有帮助:

uses
  crt, dos;

const
  daystr : array [0..6] of string[10] = (
    'Saturday', 'Sunday', 'Monday', 'Tuesday', 'Wednsday',
    'Thirsday', 'Friday');

var
  poldtimer   : pointer;
  irq8_enabled,
  rtc_int_enabled : boolean;
  int_count : integer;
  hour, minute, second,
  dayofweek,
  day, month, year, century : word;

function readcmos (reg : byte) : byte; assembler;
asm
  mov al, reg
  out $70, al
  jmp @1
@1:
  in al, $71
end;

procedure writecmos (reg, value : byte); assembler;
asm
  mov al, reg
  out $70, al
  jmp @1
@1:
  mov al, value
  out $71, al
end;

{ New IRQ8 ISR }
procedure irq8 (Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP: Word); interrupt;
begin
  inc (int_count);
  readcmos($c);                         { W/O this, RTC doesn't work }

  if irq8_enabled then
    asm
      pushf
      call dword ptr [poldtimer]        { Call to original IRQ8 ISR }
    end
  else begin
    port [$20] := $20;
    port [$a0] := $20
  end;
end;

begin
  clrscr;
  int_count := 0;
  irq8_enabled := port[$a1] and 1 = 0;
  rtc_int_enabled := readcmos ($b) and $40 = $40;

  getintvec ($70, poldtimer);                   { Save old IRQ8 ISR address }
  setintvec ($70, @irq8);                       { Set new IRQ8 ISR }

  if not irq8_enabled then
    port[$a1] := port[$a1] and $fe;             { Unmask IRQ8 }

  writecmos ($a, $26);

  if not rtc_int_enabled then
    writecmos ($b, readcmos($b) or $40);        { Enable RTC interrupt }

  writeln ('Testing IRQ8. Wait a second...');

  delay (1000);                                 { Little delay }

  if not rtc_int_enabled then
    writecmos ($b, readcmos($b) and not $40);   { Disable RTC interrupt }

  if not irq8_enabled then
    port[$a1] := port[$a1] or 1;                { Mask IRQ8 }

  setintvec ($70, poldtimer);                   { Restore old IRQ8 ISR }

  writeln ('Counts per second: ', int_count);

  writeln ('Current time and date:');
  repeat
    gotoxy (1, wherey);
    while (readcmos($a) and $80 = $80) do;
    second := readcmos(0);
    minute := readcmos(2);
    hour := readcmos(4);
    dayofweek := readcmos (6);
    day := readcmos (7);
    month := readcmos (8);
    year := readcmos (9);
    century := readcmos ($32);
    write (hour shr 4, hour and 15, ':', minute shr 4, minute and 15, ':',
           second shr 4, second and 15, ' ');
    write (day shr 4, day and 15, '/', month shr 4, month and 15, '/',
           century shr 4, century and 15, year shr 4, year and 15,
           ' [', daystr[dayofweek], ']');
  until keypressed;
  while keypressed do readkey;
  writeln
end.

它打印(在DosBox中):

Testing IRQ8. Wait a second...
Counts per second: 1048
Current time and date:
03:13:19 30/03/2012 [Friday]