You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

8086汇编:如何让定时触发int 4ah中断生效?问题求助

Troubleshooting Your 8086 Alarm Interrupt Issue

Let's break down why your INT 4AH isn't triggering after 5 seconds—there are three critical fixes needed in your code:

1. You're Not Handling Seconds Carryover

When you add 5 to the seconds register (DH), you don't account for values that exceed 59. If the current seconds are 56 or higher, adding 5 will result in an invalid second count (61-64), and the BIOS alarm function ignores invalid times. Here's how to fix the carryover:

add dh, 5       ; Add 5 seconds
cmp dh, 60
jb no_sec_carry ; If <60, no carry needed
sub dh, 60      ; Wrap around seconds to 0-59
inc cl          ; Carry over to minutes
cmp cl, 60
jb no_min_carry ; Handle minute carry if needed (rare for 5s, but safe)
sub cl, 60
inc ch          ; Carry over to hours (optional, but complete)
no_min_carry:
no_sec_carry:

2. Interrupt Vector Setup Needs Proper Interrupt Locking

When modifying the interrupt vector table, you must disable interrupts (CLI) first to prevent a race condition where an interrupt fires mid-modification, corrupting the vector. You had this code commented out—uncomment it to ensure the vector is set safely:

create_interrupt proc far
	push 0
	pop es
	pushf
	cli                     ; Disable interrupts during vector write
	mov word ptr es:[4ah*4],offset int_handler
	mov word ptr es:[4ah*4+2],seg int_handler
	sti                     ; Re-enable interrupts
	popf
	iret
create_interrupt endp

3. Your Interrupt Handler Doesn't Preserve Registers

DOS and BIOS expect interrupt handlers to preserve all registers they modify. Your int_handler changes AX and DX without saving them, which can corrupt the system state and prevent the handler from executing correctly. Fix this by pushing registers to the stack before modifying them, then popping them back:

int_handler proc far
	push ax                 ; Save registers we'll modify
	push dx
	push ds
	mov ax,DSEG
	mov ds,ax               ; Set DS to our data segment (you had this commented out—critical!)
	mov ah,09h
	mov dx,offset mess2
	int 21h
	pop ds                  ; Restore registers in reverse order
	pop dx
	pop ax
	iret
int_handler endp

Modified Full Code

Here's the complete fixed code incorporating all these changes:

SSEG segment stack
	db 256 dup(0)
SSEG ends
DSEG segment
	mess db 'Hello',0dh,0ah,'$'
	mess2 db 'Hello from handler!',0dh,0ah,'$'
	mess3 db 'Ассемблер это жопа, я уже устал','$'
DSEG ends
CSEG segment
	assume cs:CSEG,ds:DSEG,ss:SSEG
begin:
	mov ax, DSEG
	mov ds,ax
	mov ah,09h
	mov dx,offset mess
	int 21h
	call far ptr create_interrupt
	call far ptr alarm
	mov ah,01h
	int 21h
	mov ah,4ch
	int 21h

create_interrupt proc far
	push 0
	pop es
	pushf
	cli                     ; Lock interrupts during vector setup
	mov word ptr es:[4ah*4],offset int_handler
	mov word ptr es:[4ah*4+2],seg int_handler
	sti                     ; Unlock interrupts
	popf
	iret
create_interrupt endp

alarm proc far
	pushf
	mov ah,02h              ; Get current system time
	int 1ah
	; Calculate target time (current +5 seconds)
	add dh, 5
	cmp dh, 60
	jb no_sec_carry
	sub dh, 60
	inc cl
	cmp cl, 60
	jb no_min_carry
	sub cl, 60
	inc ch
no_min_carry:
no_sec_carry:
	mov ah,06h              ; Set alarm to target time
	int 1ah
	popf
	iret
alarm endp

int_handler proc far
	push ax
	push dx
	push ds
	mov ax,DSEG
	mov ds,ax
	mov ah,09h
	mov dx,offset mess2
	int 21h
	pop ds
	pop dx
	pop ax
	iret
int_handler endp
CSEG ends
end begin

One More Note

The BIOS INT 1AH AH=06h function triggers INT 4AH only once when the target time is reached. If you wanted a repeating alarm, you'd need to re-set the alarm inside the handler, but your code is set up for a single 5-second delay which this fix addresses.

内容的提问来源于stack exchange,提问作者Klepov Aleksandr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:12:55