assembly - 更改 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 命令?
- 当我回到操作系统时,我猜是“你好”。不会在内存中,但它应该打印垃圾没有?以及如何将字符串添加到内存中?
非常感谢!!!
解决方案
我想打印“你好”。每 55ns
我相信您的意思是 55毫秒(ms) 而不是纳秒(ns)。
您不需要为此目标挂钩任何中断处理程序。只需监控 BIOS.TimerTick 并在滴答声发生变化时立即打印消息。这就是下一个程序所做的。CS
可执行文件将是一个以== DS
== ES
==启动的 .COM 程序SS
。该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, '$'
当然,可以通过挂钩计时器向量来执行此操作。在没有更多特殊要求的情况下,应该将 1Ch 向量挂钩,而将 08h 向量保留。
; 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 命令行或用户应用程序)在使用屏幕时首先选择。
推荐阅读
- r - 在ggridges中,如何在没有多个脊的情况下为代码点着色?
- c++ - 更改类型后失去对 std::variant 对象的引用
- python - 如何在 codeskulptor 中每 x 秒生成一个形状?
- java - 具有构建器模式的通用对象
- python - Scrapy:提取字典存储为脚本标签中的文本
- r - R:在 2 个不同的行和列上查找重复和减法
- flutter - Flutter 文本输入块表情符号
- kotlin - Mongo 和 Kotlin 的委托问题
- android - 恢复后的闪屏问题(Flutter - Android)
- google-cloud-storage - 有没有办法将谷歌存储签名的 url 更改为不包含文件名?