ISR 后程序不断返回同一行。 (总成 8086)
Program keeps returning to same line after ISR. (Assembly 8086)
我正在处理中断,我遇到了这个问题,而 运行 我的代码:
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
在程序returns之后来自ISR(此处INT_PROC)来自IRET指令
INT_PROC PROC
MOV ERROR_FLAG, 1
IRET
它正在执行行:
DIV DIVIDER
一次又一次,而它应该去:
CMP ERROR_FLAG, 1H
Debugging Image Here
我在论坛上找到了这个,也是这么说的:
为什么会这样,我该如何解决?请帮助。
执行IRET
时,CPU会再次执行导致异常的指令。例如,这对于处理页面错误很有用。
您应该在异常处理程序中修改存储在异常堆栈中的 IP
的值,以便 CPU 执行所需的指令。
x86 架构定义了三个 类 of software-generated 中断:
- Traps,明确且有意调用中断。这些通常是
INT
指令的结果,本身并不表示有问题。推送的 IP 是后续指令的 IP,因此在处理程序的 return 之后,不会重试该指令。或者如果没有办法解决故障,它可以直接终止进程。
- 错误,例如页面错误和被零除。这些表示 un-completable 指令。推送的IP是产生故障的指令的IP;中断处理程序有机会尝试清除内容(最常见的是,通过在导致页面错误的内存页面中进行分页),然后重试指令。
- Aborts,一种本质上不可恢复的异常类型的故障(除非通过终止进程)。中断处理程序不应该 return.
在被零除的情况下,继续执行除法并不是一个好的响应,因为这样就跳过了一条指令。实际上,这些更像是中止而不是故障。中断处理程序不应该用于破解 "alternative behavior".
由于除法异常是错误,保存的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
我正在处理中断,我遇到了这个问题,而 运行 我的代码:
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
在程序returns之后来自ISR(此处INT_PROC)来自IRET指令
INT_PROC PROC
MOV ERROR_FLAG, 1
IRET
它正在执行行:
DIV DIVIDER
一次又一次,而它应该去:
CMP ERROR_FLAG, 1H
Debugging Image Here
我在论坛上找到了这个,也是这么说的:
为什么会这样,我该如何解决?请帮助。
执行IRET
时,CPU会再次执行导致异常的指令。例如,这对于处理页面错误很有用。
您应该在异常处理程序中修改存储在异常堆栈中的 IP
的值,以便 CPU 执行所需的指令。
x86 架构定义了三个 类 of software-generated 中断:
- Traps,明确且有意调用中断。这些通常是
INT
指令的结果,本身并不表示有问题。推送的 IP 是后续指令的 IP,因此在处理程序的 return 之后,不会重试该指令。或者如果没有办法解决故障,它可以直接终止进程。 - 错误,例如页面错误和被零除。这些表示 un-completable 指令。推送的IP是产生故障的指令的IP;中断处理程序有机会尝试清除内容(最常见的是,通过在导致页面错误的内存页面中进行分页),然后重试指令。
- Aborts,一种本质上不可恢复的异常类型的故障(除非通过终止进程)。中断处理程序不应该 return.
在被零除的情况下,继续执行除法并不是一个好的响应,因为这样就跳过了一条指令。实际上,这些更像是中止而不是故障。中断处理程序不应该用于破解 "alternative behavior".
由于除法异常是错误,保存的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