改变 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 个问题 -
- 即使我调用 int 21h,是否还需要 cli 和 sti 命令?
- 当我回到 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 命令行或用户应用程序)具有优先选择权。
我想打印“你好”。每 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 个问题 -
- 即使我调用 int 21h,是否还需要 cli 和 sti 命令?
- 当我回到 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 命令行或用户应用程序)具有优先选择权。