3

私は割り込みを扱っていますが、コードの実行中にこの問題に直面しています:

DATA SEGMENT
    INPUTV DW 0035H, 0855H, 2011H, 1359H
    OUTPUTV DB 4 DUP(0)
    DIVIDER DB 09
    ERROR_FLAG DB 0
DATA ENDS

_STACK SEGMENT STACK
    DW 100 DUP(0)
    TOP_STACK LABEL WORD
_STACK ENDS

CODE SEGMENT
    ASSUME CS:CODE, DS:DATA, SS:_STACK
MAIN:
    MOV AX, _STACK
    MOV SS, AX
    MOV SP, OFFSET TOP_STACK
    MOV AX, DATA
    MOV DS, AX

    MOV AX, 0000H
    MOV ES, AX
    MOV WORD PTR ES:0002, SEG INT_PROC  ;PUSHING CS TO STACK
    MOV WORD PTR ES:0000, OFFSET INT_PROC   ;PUSHING IP TO STACK

    MOV SI, OFFSET INPUTV
    MOV BX, OFFSET OUTPUTV

    MOV CX, 4H
REPEAT:
    MOV AX, [SI]
    DIV DIVIDER
    CMP ERROR_FLAG, 1H
    JE ERROR_ENCOUNTER
    MOV [BX], AL
    JMP SKIP
ERROR_ENCOUNTER:
    MOV BYTE PTR [BX], 0H
    MOV ERROR_FLAG, 0H
SKIP:
    ADD SI,2
    INC BX
    LOOP REPEAT
    INT 3H
CODE ENDS

INT_SEG SEGMENT 
    ASSUME CS:INT_SEG
INT_PROC PROC
        MOV ERROR_FLAG, 1
        IRET
    INT_PROC ENDP
INT_SEG ENDS

END MAIN

プログラムが IRET 命令から ISR (ここでは INT_PROC) から戻った後

    INT_PROC PROC
            MOV ERROR_FLAG, 1
            IRET

次の行を実行しています:

    DIV DIVIDER

それが行くはずだった間、何度も何度も:

    CMP ERROR_FLAG, 1H

デバッグ画像はこちら

同じことを言っているフォーラムでこれを見つけました:

割り込みハンドラを返した後、プログラムカウンタはどこに行きますか?

なぜそれが起こっているのですか?どうすれば解決できますか?助けてください。

4

3 に答える 3

0

除算例外はフォルトであるため、保存された CS:IP はそのDIV命令を指します。割り込みから戻るだけで、障害のある命令が再実行されます。解決策は、スタック上の IP の値を変更することです。その利点は、 ERROR_FLAG変数がまったく必要なくなったことです。

INT_PROC PROC
    pop  ax
    push ERROR_ENCOUNTER
    xor  ax, ax  ;Eliminates the need for the SKIP label and some instructions.
    iret
INT_PROC ENDP

InterruptVector0 のセットアップ中は割り込みを無効にするのが賢明であったことに注意してください。

MOV AX, 0000H
MOV ES, AX
cli
MOV WORD PTR ES:0002, SEG INT_PROC
MOV WORD PTR ES:0000, OFFSET INT_PROC
sti

あなたのループはこのようにタイトになる可能性があります:

    MOV CX, 4H
REPEAT:
    MOV AX, [SI]
    DIV DIVIDER
ERROR_ENCOUNTER:
    MOV [BX], AL
    ADD SI, 2
    INC BX
    LOOP REPEAT
于 2016-02-21T15:38:03.980 に答える