2

I'm writing the main program in Turbo-C and the functions are in assembly. My code is as follows:

lastc.c:

#include <stdio.h>
#include <dos.h>
#include <string.h>
extern void  eliminate_multiple_press(); // save old function adress in 32bit     pointer
                                    // setvect , add new function to inturupt 9
extern void  uneliminate_multiple_press(); // restore old function to inturupt 9
int main()
{
char *str;
eliminate_multiple_press();
printf("Enter a string:\n");
scanf("%s",str);
printf("the string you entered:\n");
printf("%s\n",str);

uneliminate_multiple_press();

return 0;
}

lasta.asm:

.MODEL LARGE
PUBLIC _eliminate_multiple_press
PUBLIC _uneliminate_multiple_press

.STACK 100H
.DATA
INT9SAVE DD ?
hexa_code db 0
scan_code db 0
.CODE

KEY_HANDLER PROC FAR
PUSH AX

MOV AH,0
int 16h
mov scan_code,ah
mov hexa_code,al
POP AX
iRET
KEY_HANDLER ENDP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
_eliminate_multiple_press PROC FAR

PUSH AX    
PUSH ES
MOV AX,0  
MOV ES,AX

;INT9SAVE = GETVECT(9);
MOV AX,ES:[9*4] ; **ax=c1 hex =193 dec**
MOV WORD PTR INT9SAVE,AX
MOV AX,ES:[9*4+2] **ax=15c7 hex = 5575 dec**
MOV WORD PTR INT9SAVE+2,AX

;SETVECT(9,KEY_HANDLER);
CLI
MOV WORD PTR ES:[9*4],OFFSET KEY_HANDLER ; **ES stays 0**
MOV WORD PTR ES:[9*4+2],SEG KEY_HANDLER ; **ES stays 0**
STI 
POP ES     
POP AX 
RET
_eliminate_multiple_press ENDP

;SETVECT(9,INT9SAVE);
_uneliminate_multiple_press PROC FAR
PUSH ES
PUSH AX
MOV AX,0
MOV ES,AX
CLI
MOV AX,WORD PTR INT9SAVE
MOV ES:[9*4],AX
MOV AX,WORD PTR INT9SAVE+2
MOV ES:[9*4+2],AX
STI
POP AX
POP ES
RET
_uneliminate_multiple_press ENDP



END

I can compile the files without error using this command:

tcc -ml -r- lastc.c lasta.asm

The goal of this code is to eliminate multiple (duplicate) key presses on the keyboard. If I type this sequence of characters:

334ffffghjjjj of my keyboard

The output on the screen should be

34fghj


The Problem

When I run the program lastc.exe it gets stuck at printf("enter a string:\n");. I guess I'm having a problem changing Interrupt 9h interrupt service routine to my new function key_handler

Function key_handler is not complete but at least it should END the function and continue to the end of the code

Why does my program appear to be doing nothing when the scanf is called?

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
  • 3
    Wow, what a nostalgic post :) – valdo Jan 16 '14 at 10:51
  • P.S. you may try this code on a virtual machine with a debugger, and see what happens within eliminate_multiple_press. – valdo Jan 16 '14 at 10:53
  • i updated what happens in the debugger in eliminate_multiple_press **i cant see in the debugger that the code jumps to key_handler function anywhere** – aminhalloun Jan 16 '14 at 13:42
  • Why are `eliminate_multiple_press` and `uneliminate_multiple_press` declared as interrupt handlers? They should be normal functions with a return of `RET`. The only interrupt handler is `KEY_HANDLER` which these two functions manage. Also, if you want to push a bunch of registers, I recommend `pusha` and `popa`. – lurker Jan 16 '14 at 15:19
  • Related post: http://stackoverflow.com/questions/8362168/handling-a-keyboard-interrupt-with-turbo-c-3-0 – lurker Jan 17 '14 at 12:09

2 Answers2

2

Why are eliminate_multiple_press and uneliminate_multiple_press declared as interrupt handlers? They should be normal functions with a return of RET. They are being called as functions and are not intended as responses to an interrupt.

In your C program then:

extern void eliminate_multiple_press(); // save old function adress in 32bit     pointer
                                    // setvect , add new function to inturupt 9
extern void uneliminate_multiple_press(); // restore old function to inturupt 9

And your assembly, RET instead of IRET. And you don't need to save so many registers:

_eliminate_multiple_press PROC FAR
    push ES
    push AX

    MOV AX,0
    MOV ES,AX

    ;INT9SAVE = GETVECT(9);
    MOV AX,ES:[9*4] ; **ax=c1 hex =193 dec**
    MOV WORD PTR INT9SAVE,AX
    MOV AX,ES:[9*4+2] **ax=15c7 hex = 5575 dec**
    MOV WORD PTR INT9SAVE+2,AX

    ;SETVECT(9,KEY_HANDLER);
    CLI
    MOV WORD PTR ES:[9*4],OFFSET KEY_HANDLER ; **ES stays 0**
    MOV WORD PTR ES:[9*4+2],SEG KEY_HANDLER ; **ES stays 0**
    STI

    POP AX
    POP ES
    RET
_eliminate_multiple_press ENDP


;SETVECT(9,INT9SAVE);
_uneliminate_multiple_press PROC FAR
    PUSH ES
    PUSH AX

    MOV AX,0
    MOV ES,AX

    CLI
    MOV AX,WORD PTR INT9SAVE
    MOV ES:[9*4],AX
    MOV AX,WORD PTR INT9SAVE+2
    MOV ES:[9*4+2],AX   ; Was "[27*4+2]" which is incorrect.
    STI

    POP AX
    POP ES
    RET

_uneliminate_multiple_press ENDP
lurker
  • 56,987
  • 9
  • 69
  • 103
  • so if i understand right...my key_handler should be ended with iret am i right on this one ? because it is the function that got replaced with the old function of interrupt 9 @mbratch – aminhalloun Jan 16 '14 at 17:21
  • @aminhalloun yes. `KEY_HANDLER` is your interrupt handler to replace the old one, so it needs `IRET` and to save registers (I recommend `pusha` and `popa` if you're not sure what registers `int 16h` is modifying). The functions you are calling from C are not interrupt handlers. – lurker Jan 16 '14 at 17:23
  • i updated my code up there..but still my exe flie is getting stuck at printf function!! i cant figure out what is the problem ? – aminhalloun Jan 16 '14 at 17:32
  • @aminhalloun The code still looks the same in C: you are declaring the called functions as `interrupt`. Also, the asm instruction `MOV ES:[27*4+2],AX` is incorrect. – lurker Jan 16 '14 at 17:34
  • it should be 9 not 27 i got confused there -updated- but still..getting stuck :/ – aminhalloun Jan 16 '14 at 17:43
  • @aminhalloun I'm not sure what version of `KEY_HANDLER` you're testing, but the one you show in your problem statement obviously won't return the actual key pressed. So your `scanf` may not return since it needs to see a CR. – lurker Jan 16 '14 at 17:50
  • ok now i understand more, lets say i want the key_handler to act as usual ( it won't eliminate multiple press ) my idea is to use int16h,ah 0 and move the hexa code to the adress that *str points to, then by adding 4 decimal to the address ill fill up the next "solt". getting out of this loop is by comparing the scan code or hexa code to "enter" or "esc" – aminhalloun Jan 16 '14 at 18:00
  • The main thing that i dont understand is how does the original int 9 work and how is it connected to scanf function and *str? – aminhalloun Jan 16 '14 at 18:30
  • Int 9 is a hardware interrupt, invoked by irq 1 in response to a key press or key release. The only thing it "returns" is to put the keystroke (ascii code and scan code) in the keyboard buffer in the BIOS Data Area. A DOS implementation of the C library `scanf` would get keystrokes from there, probably via int 21h... unless it's redirected (myprog – Frank Kotler Jan 16 '14 at 20:17
-2

An End Of Interrupt (EOI) is a signal sent to a Programmable Interrupt Controller (PIC) to indicate the completion of interrupt processing for a given interrupt.

mov al,020h ; =EOI
out 020h,al
brasofilo
  • 25,496
  • 15
  • 91
  • 179