Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

interrupt-Syntax bei Borland C 4.5

12 views
Skip to first unread message

Phillip Hauser

unread,
Apr 9, 1999, 3:00:00 AM4/9/99
to
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, ...

Danke.
Phillip

--
Phillip Hauser
eMail: pha...@gmx.de
Homepage: www.surf.to/phauser

Gerhard Strangar

unread,
Apr 9, 1999, 3:00:00 AM4/9/99
to
Phillip Hauser schrob:

> 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}
?


Phillip Hauser

unread,
Apr 10, 1999, 3:00:00 AM4/10/99
to
Hi

> 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??

Phillip

Gerhard Strangar

unread,
Apr 10, 1999, 3:00:00 AM4/10/99
to
Phillip Hauser schrob:

> > 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

Moment, warum ist dein INT-Handler near?
Sollte doch eigentlich far sein, oder?
Dann würde der Compiler wahrscheinlich mit einem RETF beenden und du
müsstest nur dafür sorgen, daß die Flags vom Stack runter kommen.

> 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

Da würde ich den "schmutzigen" Weg gehen und einfach dem Compiler
dreinpfuschen und statt meinem vorgeschlagenen _asm { iret } ein
_asm {
pop eax
pop ebp
iret }
verwenden.


Andere Möglichkeit: Du definierst am Anfang deines INT-Handlers ein Label
und lässt dann den INT-Vektor auf dieses Label zeigen und nicht auf den
Anfang der vom Compiler erzeugten Routine.


Oder du machst es so, wie die Typen von der Online-Hilfe vom BC++ 5.02:
/* Beispiel _chain_intr */

Wenn du dieses Beispiel nicht hast, dann kann ich es dir mailen, aber bitte
nicht fragen, wie es funktioniert.


Met vriendelijke groeten
Gerhard


Michael Tippach

unread,
Apr 10, 1999, 3:00:00 AM4/10/99
to
In article <7en36v$9tj$1...@news05.btx.dtag.de>, Phillip Hauser
<j.ha...@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
dclax...@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< -----------------------


TKU

unread,
Apr 12, 1999, 3:00:00 AM4/12/99
to
> Weiss nun jemand den "echten" Syntax zur interrupt-Dekleration in Borland C
> 4.5??
>
> Phillip

Ich glaube bei Borland gibt es ein Schlüsselwort
"interrupt"; Einfach mal in der Online-Hilfe
nachsehen.

Timo

0 new messages