the following program is a TSR proram that will output the character 'A' every 15 microseconds.it intercepts interupt 8 to output the character and then resumes int8.i couldn't get it to work with CALL but i managed to get it to work using jmp and modifying the the way the address is stored in 'OLDINT8'.pls help me identify the mistake
thanks
CODESG SEGMENT
ASSUME CS:CODESG
ORG 100H
MAIN: JMP SHORT LOAD
OLDINT8 DD ? ;STORE CS:IP OF INT8
NEWINT8 PROC FAR
PUSH AX ;SAVE REGISTER
MOV AH,0EH ;OUTPUT CHARACTER
MOV AL,41H
INT 10H
POP AX
CALL DWORD PTR [OLDINT8] ;CALL ORIGINAL INT8
IRet
NEWINT8 EndP
ASSUME CS:CODESG,DS:CODESG
LOAD PROC NEAR
MOV AH,35H ;GET INTERUPT 08H
MOV AL,8H
INT 21H
MOV WORD PTR OLDINT8,ES ;SAVE IT
MOV WORD PTR OLDINT8+2,BX
MOV AH,25H ;SET NEW LOCATION
MOV AL,08H
MOV DX,OFFSET NEWINT8
INT 21H
MOV DX,(OFFSET LOAD - OFFSET CODESG) ;find how how many bytes resident
ADD DX,15 ;make it
MOV CL,4 ;multiple of 16 bytes
SHR DX,CL
MOV AH,31H ;and make it
INT 21H ;resident
LOAD ENDP
CODESG ENDS
END MAIN
hi xxxx,
this code:
MOV WORD PTR OLDINT8,ES ;SAVE IT
MOV WORD PTR OLDINT8+2,BX
is a severe bug, should be
MOV WORD PTR OLDINT8+2,ES ;SAVE IT
MOV WORD PTR OLDINT8+0,BX
to use the call instruction, you would have to create an IRET stack frame, that is, pushing the flags before the call. But in this case it's
better to simply use
jmp DWORD PTR cs:[OLDINT8] ;CALL ORIGINAL INT8
I commented all of the problems and unnecessary components I can see, but there may be others.
CODESG SEGMENT
;; For MASM 6+, MASM automatically assumes CS is
;; set to the current segment, so ASSUME CS: is
;; not necessary.
ASSUME CS:CODESG
ORG 100H
MAIN:
JMP SHORT LOAD
OLDINT8 DD ? ;STORE CS:IP OF INT8
NEWINT8 PROC FAR
;; From Ralf Brown's Interrupt List:
;; INT 10 - VIDEO - TELETYPE OUTPUT
;; AH = 0Eh
;; AL = character to write
;; BH = page number
;; BL = foreground color (graphics modes only)
;; Return: nothing
;; So you need to set BH to the display page
;; number the you want the output to be written
;; to. For the default text mode the default
;; display page is page 0, so you would normally
;; set BH to 0. And because you are changing the
;; value in BX, you need to preserve it just as
;; you are preserving AX.
PUSH AX ;SAVE REGISTER
MOV AH,0EH ;OUTPUT CHARACTER
MOV AL,41H
INT 10H
POP AX
; Multiple problems here.
;
; When a hardware interrupt handler is called, the
; only segment register with a known value is CS,
; so you must access your resident data relative to
; the code segment by using a CS: segment override.
;
; Before the processor jumps to an interrupt handler,
; it pushes the flags, CS, and IP in that order.
; The IRET instruction effectively pops IP, CS, and
; the flags (in that order) before it returns to the
; interrupted process. So to chain to the next handler
; with a far call, you must first push the flags onto
; the stack so the IRET instruction at the end of the
; handler chain will not cause a stack imbalance.
; And because the processor always clears interrupts
; before it jumps to an interrupt handler, you must
; also execute a CLI after pushing the flags and
; before the the CALL.
;
; But you generally chain with a far call only when
; you need to do further processing after the call
; returns to your handler. In this case you do not,
; so you can just chain with a far jump. And because
; OLDINT8 is defined as a dword, you do not need to
; specify DWORD PTR:
JMP CS:OLDINT8
;CALL DWORD PTR [OLDINT8] ;CALL ORIGINAL INT8
;IRet
NEWINT8 EndP
ASSUME CS:CODESG,DS:CODESG
LOAD PROC NEAR
MOV AH,35H ;GET INTERUPT 08H
MOV AL,8H
INT 21H
;; For a far (dword) address, the segment address
;; is stored in the word at the highest address,
;; So as Gustav pointed out, your registers are
;; reversed here. The WORD PTR is necessary here
;; because you are accessing the data as words
;; when it was defined as a dword.
MOV WORD PTR OLDINT8,ES ;SAVE IT
MOV WORD PTR OLDINT8+2,BX
MOV AH,25H ;SET NEW LOCATION
MOV AL,08H
MOV DX,OFFSET NEWINT8
INT 21H
MOV DX,(OFFSET LOAD - OFFSET CODESG) ;find bytes resident
ADD DX,15 ;make it
MOV CL,4 ;multiple of 16 bytes
SHR DX,CL
MOV AH,31H ;and make it
INT 21H ;resident
LOAD ENDP
CODESG ENDS
END MAIN
thank you