News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

TSR program

Started by xxxx, March 10, 2005, 05:16:56 PM

Previous topic - Next topic

xxxx

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



Gustav


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


MichaelW

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

eschew obfuscation

xxxx