改变 IRQ8 中断服务程序

Change IRQ8 ISR

我想打印“你好”。每 55ns。我做错了什么?

.model small
.stack 100h

pusha MACRO
    push ax
    push bx
    push cx
    push dx
    push sp
    push bp
    push si
    push di
ENDM

popa MACRO
    pop di
    pop si
    pop bp
    pop sp
    pop dx
    pop cx
    pop bx
    pop ax
ENDM



.data
    old_vec dw 1  dup(?)
    old_seg dw 1  dup(?)
    HELLO db "HELLO.$"
    

.code
start:
    mov ax, @data
    mov ds, ax
    mov ax, es:[20h]
    mov bx, es:[20h+2] ;saving the old ISR ADDRESS
    mov old_vec, ax
    mov old_seg, bx
    mov es:[20h], OFFSET PRINT_HELLO ; setting the ivt to point to PRINT_HELLO
    mov es:[20h + 2], SEG PRINT_HELLO

    COMMENT @
    mov bx, offset old_vec
    mov ax, word ptr[bx]
    mov es:[20h], ax
    mov bx, offset old_seg
    mov ax, word ptr[bx]
    mov es:[20h+2], ax
    @

    ;for1:
    ;   jmp for1

    .exit
    mov ah, 4ch
    int 21h

PRINT_HELLO proc far
    pushf
    pusha
    mov ax, offset old_seg
    mov bx, ax
    mov es, word ptr[bx]
    mov bx, offset old_vec
    mov bx, word ptr[bx]
    call far PTR es:[bx] ; calling the old interrupt handler
    mov dx, offset HELLO
    mov ah, 09h
    int 21h
    popa
    iret
PRINT_HELLO endp


end

注释用于调试...

还有 2 个问题 -

  1. 即使我调用 int 21h,是否还需要 cli 和 sti 命令?
  2. 当我回到 OS 时,我猜是“你好”。不会在内存中,但它应该打印垃圾不是吗?以及如何将字符串添加到内存中?

非常感谢!!!

I want to print "Hello." every 55ns

我相信你的意思是 55 milliseconds (ms) 而不是 nanoseconds (ns)。

您不需要为此 objective 挂钩任何中断处理程序。它所要做的就是监视 BIOS.TimerTick 并在刻度更改时立即打印消息。这就是下一个程序所做的。可执行文件将是一个以 CS==DS==ES==SS 启动的 .COM 程序。 ORG 256 指令是强制性的。

; This program prints a message every 55 milliseconds
; until a key is pressed

        ORG     256

        xor     ax, ax
        mov     es, ax
More:   mov     al, [es:046Ch]    ; BIOS.Timer
Wait:   cmp     al, [es:046Ch]
        je      Wait
        mov     dx, Msg
        mov     ah, 09h           ; DOS.PrintString
        int     21h
        mov     ah, 01h           ; BIOS.TestKey
        int     16h               ; -> AX ZF
        jz      More
        mov     ah, 00h           ; BIOS.GetKey
        int     16h               ; -> AX
        mov     ax, 4C00h         ; DOS.Terminate
        int     21h
; --------------------------------
Msg     db      'Hello, once every 55 milliseconds!', 13, 10, '$'

当然可以挂接计时器向量。在没有更多特殊要求的情况下,hook 1Ch vector,08h vector留着。

; This program prints a message every 55 milliseconds
; until a key is pressed

        ORG     256

        mov     ax, 351Ch         ; DOS.GetInterruptVector
        int     21h               ; -> ES:BX
        mov     [chain+1], bx
        mov     [chain+3], es

        mov     dx, int1C
        mov     ax, 251Ch         ; DOS.SetInterruptVector
        int     21h

vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
; In the 'main' part you can freely change DS, ES, and SS segment registers
main:   mov     ah, 01h           ; BIOS.TestKey
        int     16h               ; -> AX ZF
        jz      main
        mov     ah, 00h           ; BIOS.GetKey
        int     16h               ; -> AX
; In the 'main' part you can freely change DS, ES, and SS segment registers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

        mov     dx, [cs:chain+1]
        mov     ds, [cs:chain+3]
        mov     ax, 251Ch         ; DOS.SetInterruptVector
        int     21h
        mov     ax, 4C00h         ; DOS.Terminate
        int     21h
; --------------------------------
int1C:  push    ax bx si
        cld
        mov     bx, 0007h         ; DisplayPage and GraphicsColor
        mov     si, Msg
.more:  lods byte [cs:si]
        mov     ah, 0Eh           ; BIOS.Teletype
        int     10h
        cmp     al, 10
        jne     .more
        pop     si bx ax    
chain:  jmp far 0:0               ; Chaining to the old interrupt handler
Msg:    db      'Hello, once every 55 milliseconds!', 13, 10, '$'
; --------------------------------
  • 使用BIOS输出功能避免DOS重入问题。
  • 将旧向量存储在远跳转指令上使您不必操作段寄存器。
  • 将消息放在代码段中便于访问。
  • DOS 函数 25h 和 35h 在更改中断向量时很容易使用。

我使用了 FASM 汇编程序。即使您使用的是 MASM 风格的汇编程序,您能否从这些示例中学习...


虽然可以通过 TSR 完成上述所有操作,但将这么多文本字符快速连续地放在屏幕上将不可避免地造成真正的混乱!请记住,在使用屏幕时,前台程序(DOS 命令行或用户应用程序)具有优先选择权。