Dos 汇编程序在中断期间挂起
Dos Assembly Program hanging during Interrupt
以下程序在没有错误或警告的情况下进行汇编。但是,当我 运行 它在顶部显示 "ABK" 然后挂起 DosBox。
我正在使用 nasm 汇编程序和 DosBox。
我写
nasm eex9_2.asm -o eex9_2.com
[org 0x100]
jmp start
oldisr: dd 0
kbisr: push ax
push es
mov ax, 0xb800
mov es, ax
xor ax, ax
in al, 0x60
mov byte [es:0], 'A'
mov byte [es:2], 'B'
mov byte [es:4], 'K'
mov al, 0x20
out 0x20, al
pop es
pop ax
iret
start: xor ax, ax
mov es, ax
mov ax, [es:9*4]
mov [oldisr], ax
mov ax, [es:9*4+2]
mov [oldisr+2], ax
mov word [es:9*4], kbisr ; store offset at n*4
mov [es:9*4+2], cs
mov dx, start
add dx, 6
mov cl, 4
shr dx, cl
mov ax, 0x3100
int 21h
你的程序有两个问题:
更小的一个是下面两行:
mov word [es:9*4], kbisr
mov [es:9*4+2], cs
如果在两条指令的第一条指令之后接收到一些键盘输入,系统将崩溃,因为中断处理程序地址错误(它是 "old" 段和 "new" 偏移量)。
您应该执行以下操作:
cli
mov word [es:9*4], kbisr
mov [es:9*4+2], cs
sti
然而,主要问题 是 Michael Petch 所写的问题:
操作系统使用中断获取键盘输入。如果您键入:
C:\>dir
中断将被调用8次:
- 按下"D"一次
- 释放"D"时一次
- ...
- 释放 return 键时一次
每次按下一个键时,中断都会读取键数据(就像您的中断所做的那样)并将数据写入内存。操作系统(或其他程序)会读出内存中的数据,就知道你输入了"dir".
如果您安装自己的键盘中断,则不会有数据写入该内存(除非您的中断这样做),因此没有程序可以再读取键盘!
如果您对来自键盘的数据(实际按下的键)不感兴趣,您可以按照 Michael Petch 的建议进行操作:
kbisr: push ax
push es
mov ax, 0xb800
mov es, ax
mov byte [es:0], 'A'
mov byte [es:2], 'B'
mov byte [es:4], 'K'
pop es
pop ax
jmp far [cs:oldisr]
(我不确定最后一行的语法是否正确,因为我使用的 GNU 汇编器使用的语法不同于 nasm。)
最后一行将跳转到原始中断,它将执行...
- ...端口0x60的读取
- ... 将 0x20 写入端口 0x20
- ...将键盘数据写入内存(你不会做的)
- ... IRET
如果您需要知道按下了哪个键并且您希望 OS 正常工作,您几乎没有机会...
以下程序在没有错误或警告的情况下进行汇编。但是,当我 运行 它在顶部显示 "ABK" 然后挂起 DosBox。 我正在使用 nasm 汇编程序和 DosBox。 我写
nasm eex9_2.asm -o eex9_2.com
[org 0x100]
jmp start
oldisr: dd 0
kbisr: push ax
push es
mov ax, 0xb800
mov es, ax
xor ax, ax
in al, 0x60
mov byte [es:0], 'A'
mov byte [es:2], 'B'
mov byte [es:4], 'K'
mov al, 0x20
out 0x20, al
pop es
pop ax
iret
start: xor ax, ax
mov es, ax
mov ax, [es:9*4]
mov [oldisr], ax
mov ax, [es:9*4+2]
mov [oldisr+2], ax
mov word [es:9*4], kbisr ; store offset at n*4
mov [es:9*4+2], cs
mov dx, start
add dx, 6
mov cl, 4
shr dx, cl
mov ax, 0x3100
int 21h
你的程序有两个问题:
更小的一个是下面两行:
mov word [es:9*4], kbisr
mov [es:9*4+2], cs
如果在两条指令的第一条指令之后接收到一些键盘输入,系统将崩溃,因为中断处理程序地址错误(它是 "old" 段和 "new" 偏移量)。
您应该执行以下操作:
cli
mov word [es:9*4], kbisr
mov [es:9*4+2], cs
sti
然而,主要问题 是 Michael Petch 所写的问题:
操作系统使用中断获取键盘输入。如果您键入:
C:\>dir
中断将被调用8次:
- 按下"D"一次
- 释放"D"时一次
- ...
- 释放 return 键时一次
每次按下一个键时,中断都会读取键数据(就像您的中断所做的那样)并将数据写入内存。操作系统(或其他程序)会读出内存中的数据,就知道你输入了"dir".
如果您安装自己的键盘中断,则不会有数据写入该内存(除非您的中断这样做),因此没有程序可以再读取键盘!
如果您对来自键盘的数据(实际按下的键)不感兴趣,您可以按照 Michael Petch 的建议进行操作:
kbisr: push ax
push es
mov ax, 0xb800
mov es, ax
mov byte [es:0], 'A'
mov byte [es:2], 'B'
mov byte [es:4], 'K'
pop es
pop ax
jmp far [cs:oldisr]
(我不确定最后一行的语法是否正确,因为我使用的 GNU 汇编器使用的语法不同于 nasm。)
最后一行将跳转到原始中断,它将执行...
- ...端口0x60的读取
- ... 将 0x20 写入端口 0x20
- ...将键盘数据写入内存(你不会做的)
- ... IRET
如果您需要知道按下了哪个键并且您希望 OS 正常工作,您几乎没有机会...