Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion interrupt-Syntax bei Borland C 4.5
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Michael Tippach  
View profile   Translate to Translated (View Original)
 More options Apr 10 1999, 3:00 am
Newsgroups: de.comp.lang.assembler.x86
From: Michael Tippach <Spammer.Drop.D...@wuschel.demon.co.uk>
Date: 1999/04/10
Subject: Re: interrupt-Syntax bei Borland C 4.5
In article <7en36v$9t...@news05.btx.dtag.de>, Phillip Hauser
<j.hau...@t-online.de> writes

>Hi

>>> Weiss da draussen jemand den Syntax wenn ich eine Funktion bei Borland C
>>> 4.5 als Interrupt-Funktion deklarieren will? Also so das die Funktion
>>> mit einem iret zurückkehrt, ...

>> mit _asm {iret} ?

>Nee nee! Dann wär's ja einfach! Der Compiler richtet in so einer Funktion
>(Handler) ja auch einen Stackrahmen ein! Und wenn ich das iret() da einsetze,
>dann sieht das so aus:

>handler proc near
>               push    ebp                     ; Stackrahmen
>               mov     ebp,esp
>               push    eax                     ; braucht er vielleicht

>; den handler-code
>               [...]

>; _asm { iret };
>               iret                            ; und hier kommt meins dann so
>(vor den POPs)!

>               pop     eax
>               pop     ebp
>               ret                             ; <- aber hier sollte es rein!!
>(das iret)
>handler endp

>Ausserdem macht der Compiler (wenn man eine Funktion als "interrupt"
>deklariert) noch
>andere spezielle Sachen dazu, die er sonst nicht machen würde. Tja.

>Weiss nun jemand den "echten" Syntax zur interrupt-Dekleration in Borland C
>4.5??

Fuer 16 bit code: void interrupt ihandler(){}

Fuer 32 bit code allerdings haben Borland "interrupt" weg-erfunden. Da
Du nix zum Target gesagt hast (32 bit DPMI, Win32(???) oder gar ein
selbst geschriebenes run- time environment?) gibt es keine
allgemeingueltige Antwort.

Der "interrupt"- Modifier ist in BCC32.EXE ueberhaupt nicht definiert.
Ein einfaches iretd und das vorherige Breittreten des Stackframes
reichen meisstens nicht, da die Interrupt- Prozedur gelegentlich auf
einem anderen Stack laueft (d.h. base(cs) != base(ss)), DS ebenfalls
reichlich undefiniert ist und obendrein zumindest der Intel- Referenz-
Compiler in BC 5 ueberhaupt gar keinen Stackframe generiert, sondern
Parameter und lokale Variablen direkt ueber [esp] adressiert. Dein
Programm wuerde also dann mit BC 5 ggf. nicht mehr laufen.

Fuer 32 bit DPMI hab ich mir irgendwann 'mal eine DLL geschrieben, die
hier generell Abhilfe schafft. Da der (TASM) Source code nicht allzu
umfangreich ist, hab' ich diesen hier angehaengt. Die DLL erlaubt es,
Interrupt- Handler als ganz normale NEAR- Routinen zu verwalten. Im
gegenwaertigen Zustand ist sie allerdings nur fuer Hardware- Interrupts
ausgelegt.

Funktioniert mit MSVC++ genauso wie mit BC++ Hier ist ein Besipiel, wie
das dann in C aussieht:

----------------------- 8< ----------------------
#include "pmirq.h"
#include <conio.h>

void (*OldHandler)();

void NewHandler() {
   unsigned char *p;
   p = 0xB8000;
   ++ (*p);
   OldHandler();

}

int main() {
   OldHandler = GetIRQHandler(0);
   SetIRQHandler(0, NewHandler);
   while (!kbhit());
   SetIRQHandler(0, OldHandler);
   return(0);
}

---------------------- 8< -----------------------

Fuer 32rtm als DOS extender muesste ggf. der Bildschirmzugriff etwas
modifiziert werden (base(DS != 0) in 32rtm).

Hier ist pmirq.h:

---------------------- 8< -----------------------
#if !defined(__PMIRQ_H)
#define __PMIRQ_H

void (*__stdcall GetIRQHandler(int))();
void __stdcall SetIRQHandler(int, void());

#endif /* __PMIRQ_H */
---------------------- 8< -----------------------

Und hier die Source fuer pmirq.dll. Email an
dclax990...@wuschel.demon.co.uk
wer das Binary haben will.

Gruss,

Michael
---------------------- 8< -----------------------

;-----------------------------------------------------------------------
; Configuration parameters
;
NUM_INTERRUPT_STACKS = 4
INTERRUPT_STACK_SIZE = 1000h

;-----------------------------------------------------------------------
; TASM red tape
;
.386
.model flat
.code

        PUBLICDLL       SetIRQHandler
        PUBLICDLL       GetIRQHandler

SIZE_OF_ENTRY   EQU ((OFFSET __entryEnd-OFFSET __entryStart) SHR 4)
SIZE_OF_WRAPPER EQU ((OFFSET __wrapperEnd-OFFSET __wrapperStart) SHR 4)

;+----------------------------------------------------------------------
; DLL Entry point
;
DllMain PROC NEAR
        pushad
        mov     DataSelector, ds
        mov     TIBSelector, fs
        mov     ebx, 8
        mov     edi, OFFSET __wrapperStart
        mov     esi, OFFSET __entryStart

@@getSetLoop:
        mov     eax, 0204h
        int     31h
        mov     [edi + SIZE_OF_WRAPPER - 8], edx
        mov     [edi + SIZE_OF_WRAPPER - 4], ecx
        mov     edx, esi
        mov     ecx, cs
        mov     eax, 0205h
        int     31h
        add     esi, SIZE_OF_ENTRY
        add     edi, SIZE_OF_WRAPPER    
        inc     ebx
        cmp     ebx, 78h
        je      @@getSetDone

        cmp     ebx, 16
        jne     @@getSetLoop

        mov     ebx, 70h
        jmp     @@getSetLoop

@@getSetDone:
        popad
        mov     eax, 1
        retn    12
DllMain ENDP

;-----------------------------------------------------------------------
; The actual interrupt glue code
;
EnterInterrupt PROC NEAR
        xchg    ecx, [esp]
        push    eax
        push    edx
        push    gs
        push    fs
        push    es
        push    ds
        mov     ds, DWORD PTR cs:[OFFSET DataSelector]
        mov     fs, TIBSelector
        mov     edx, ss
        mov     eax, esp
        sub     DWORD PTR [OFFSET IntStackTop], INTERRUPT_STACK_SIZE
        push    ds
        push    ds
        pop     es
        pop     ss
        mov     esp, DWORD PTR [OFFSET IntStackTop]
        push    edx
        push    eax
        call    ecx
        lss     esp, [esp]
        add     DWORD PTR [OFFSET IntStackTop], INTERRUPT_STACK_SIZE
        pop     ds
        pop     es
        pop     fs
        pop     gs
        pop     edx
        pop     eax
        pop     ecx
        iretd
EnterInterrupt ENDP

;-----------------------------------------------------------------------
; Standard interrupt entry points
;
__entryStart LABEL NEAR
i = 0
REPT 16
IrqEntry CATSTR <Irq>,%i,<Entry>
IrqEntry LABEL NEAR
        call    EnterInterrupt
        jmp     DWORD PTR [OFFSET HandlerArray + i * 4]
        i = i + 1
ENDM
__entryEnd LABEL NEAR

;-----------------------------------------------------------------------
; NEAR callable irq handler entries with IRET stackframe
;
__wrapperStart LABEL NEAR
i = 0
REPT 16
        xchg    eax, [esp]
        push    eax
        push    eax
        pushfd
        pop     eax
        xchg    [esp + 8], eax
        mov     [esp + 4], cs
        db      0EAh
        dd      ?
        dd      ?
        i = i + 1
ENDM
__wrapperEnd LABEL NEAR

;+----------------------------------------------------------------------
; GetIrqHandler
;
GetIrqHandler PROC NEAR
        mov     eax, [esp + 4]
        mov     eax, [eax * 4 + OFFSET HandlerArray]
        retn    4
GetIrqHandler ENDP

;+----------------------------------------------------------------------
; SetIrqHandler
;
SetIrqHandler PROC NEAR
        mov     edx, [esp + 4]
        mov     eax, [esp + 8]
        mov     [edx * 4 + OFFSET HandlerArray], eax
        retn    8
SetIrqHandler ENDP

.data

HandlerArray LABEL DWORD
i = 0
REPT 16
        dd      OFFSET __wrapperStart + i * SIZE_OF_WRAPPER
        i = i + 1
ENDM

IntStackTop     dd      OFFSET TheTopOfStack

.data?
DataSelector    dd      ?
TIBSelector     dd      ?
                db NUM_INTERRUPT_STACKS * INTERRUPT_STACK_SIZE DUP (?)
TheTopOfStack   LABEL   DWORD

END     DllMain
---------------------- 8< -----------------------


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.