简体   繁体   English

装配16位中断

[英]Assembly 16-bit interrupts

; another attempt to terminate program with Esc that hooks
; keyboard interrupt
    [org 0x100]
    jmp start
    oldisr: dd 0 ; space for saving old isr
; keyboard interrupt service routine
kbisr: push ax
    push es
    mov ax, 0xb800
    mov es, ax ; point es to video memory
    in al, 0x60 ; read a char from keyboard port
    cmp al, 0x2a ; is the key left shift
    jne nextcmp ; no, try next comparison
    mov byte [es:0], 'L' ; yes, print L at top left
    jmp nomatch ; leave interrupt routine
    nextcmp: cmp al, 0x36 ; is the key right shift
    jne nomatch ; no, leave interrupt routine
    mov byte [es:0], 'R' ; yes, print R at top left
    nomatch: ; mov al, 0x20
; out 0x20, al
    pop es
    pop ax
    jmp far [cs:oldisr] ; call the original ISR
; iret
start: xor ax, ax
    mov es, ax ; point es to IVT base
    mov ax, [es:9*4]
    mov [oldisr], ax ; save offset of old routine
    mov ax, [es:9*4+2]
    mov [oldisr+2], ax ; save segment of old routine
    cli ; disable interrupts
    mov word [es:9*4], kbisr ; store offset at n*4
    mov [es:9*4+2], cs ; store segment at n*4+2
    sti ; enable interrupts
l1: mov ah, 0 ; service 0 – get keystroke
    int 0x16 ; call BIOS keyboard service
    cmp al, 27 ; is the Esc key pressed
    jne l1 ; if no, check for next key
    mov ax, 0x4c00 ; terminate program
    int 0x21

I'm wonder that why we can only use cs:offset for the purpose to call oldIsr in this program. 我想知道为什么我们只能使用cs:offset来调用这个程序中的oldIsr。 Why just CS ??? 为什么只是CS ???

AT THIS LINE 在这条线上

jmp far [cs:oldisr] ; call the original ISR

WHAT is the purpose behind the it? 这背后的目的是什么? Please explain it!!! 请解释一下!!!

Inside 16b real mode interrupt handler code you don't know the values of segment registers, they can be anything. 在16b实模式中断处理程序代码中你不知道段寄存器的值,它们可以是任何东西。 Usually you can expect at least stack ( ss:sp ) to be reasonably valid and large enough to store return address and few bytes for handler, and also cs is fixed to the handler code, because in case of different cs value the CPU would execute some different instructions, not yours. 通常你可以期望至少stack( ss:sp )合理有效并且足够大以存储返回地址和少量字节用于处理程序,并且cs也固定到处理程序代码,因为在cs值不同的情况下CPU将执行一些不同的指示,而不是你的。

So to avoid hassle of storing old/unknown ds , setting up data segment of handler variables, and accessing them through ds: prefixes, then restoring ds back, it is easier to have the variable next to the code itself, and address it by cs:oldisr , as the value of cs is known to be what you need. 因此,为了避免存储旧的/未知的ds ,设置处理程序变量的数据段,并通过ds:前缀访问它们,然后将ds还原,更容易将变量放在代码本身旁边,并通过cs:oldisr解决它cs:oldisr ,因为cs的值已知是你需要的。


I will try to write it in more simple way: 我将尝试以更简单的方式编写它:

mov ax,[si] is by default using ds (*1), ie it is actually doing mov ax,[ds:si] . mov ax,[si]默认使用ds (* 1),即它实际上是做mov ax,[ds:si]

You can override the default by writing the segment register explicitly like mov ax,[cs:si] . 您可以通过显式写入段寄存器来覆盖默认值,如mov ax,[cs:si]

Physical memory address in 16b real mode is: segment_value*16+offset_value 16b实模式下的物理内存地址为:segment_value * 16 + offset_value

When the code does enter your ISR handler, you do NOT know, what the running code had in ds or es at the moment of interrupt. 当代码进入你的ISR处理程序时,你不知道在中断时ds / es中正在运行的代码是什么。 It may point anywhere in the memory (NOT to your variables!). 它可能指向内存中的任何位置(而不是你的变量!)。

But you know, that cs points to your handler instructions (otherwise CPU would execute instructions elsewhere, because CPU does execute next instruction from memory at cs:ip ). 但是你知道, cs指向你的处理程序指令(否则CPU会在别处执行指令,因为CPU确实在cs:ip执行来自内存的下一条指令)。

Just look how your handler has to preserve/set/restore es , that's example what you would have to do with ds , to be able to use the ds . 只需看看你的处理程序如何保存/设置/恢复es ,这就是你必须使用ds做的一个例子,以便能够使用ds

The cs is already preserved on stack, set to your code segment, and IRET (in old handler) will restore it. cs已经保存在堆栈中,设置为您的代码段,而IRET (在旧处理程序中)将恢复它。


1) The bp is using by default ss , the stos/movs/cmps are using by default both ds and es , and only the source ds can be overridden, the es for target is fixed. 1) bp默认使用ssstos/movs/cmps默认使用dses ,只有源ds可以被覆盖,目标的es是固定的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM