UART 16550

Gast #546664
Lesenswert?

Hallo, ja und zwar möchte ich das ganze Vorgehen für die ISR bzw COM 
Interrupt Handler beschreiben.
1
void __cdecl CommIntHandler(ETSINTREGS *pRegs);
2

3
void COM(void)
4
{
5
...
6
UartIntVecNum = EtsPicGetIRQIntNumber(UartIRQNum); 
7
// UartIntVecNum = 0x0C
8
SaveFlags = EtsSetInterruptFlag(ETS_DISABLEINTS);
9
EtsSaveInterruptHandler(UartIntVecNum, &CommDesc);
10
EtsSetInterruptHandler( UartIntVecNum, CommIntHandler); // set handler
11
...
12
}

//
// Saved register block passed to interrupt handlers registered
// with EtsSetInterruptHandler() and EtsSetExceptionHandler().
// These fields contain the register contents at the time of the
// interrupt.  The interrupt service routine can modify the
// values in the passed structure in order to change the user
// registers on return from the interrupt.
//
// Note:  The FS and GS registers are neither saved nor restored
// by the interrupt handler framework.  If a user interrupt handler
// wants to use either of these registers, it must preserve them itself!
//
typedef struct tagETSINTREGS
{
  DWORD   Ebp;                    // [00]
  DWORD   Eax;                    // [04]
  DWORD   Ebx;                    // [08]
  DWORD   Ecx;                    // [12]
  DWORD   Edx;                    // [16]
  DWORD   Esi;                    // [20]
  DWORD   Edi;                    // [24]
  DWORD   Gs;                     // [28]
  DWORD   Ds;                     // [32]
  DWORD   Es;                     // [36]
  DWORD   IntNum;                 // [40]
  DWORD   Ecode;                  // [44]
                           (Zero if int w/o error code)
  DWORD   Eip;                    // [48]
  DWORD   Cs;                     // [52]
  DWORD   Eflags;                 // [56]
} ETSINTREGS, *PETSINTREGS;

//---------------------------------------------------------------------- 
-------
// EtsSetInterruptHandler - Install a C function as an interrupt handler
//
//      This API installs a C function as an interrupt handler
//      for the specified interrupt.  The handler is entered as a normal
//      C function (__cdecl calling sequence) with interrupts disabled
//      and receives a pointer to the saved register set on the stack
//      as its argument.  The saved register set includes all general
//      purpose registers, DS, ES, and EFLAGS.  The FS and GS registers
//      are neither saved nor restored; if the handler alters them, it
//      must restore them itself before returning.  The handler
//      is expected to process the interrupt and may modify the
//      saved register set on the stack if wishes to
//      alter the context of the interrupted code.  When the handler 
function
//      returns, the saved registers are popped off the stack and
//      control returns to the interrupted code.
//
//      The return value from the function is TRUE if successful or 
FALSE
//      if an error occurs.
//
//---------------------------------------------------------------------- 
-------
BOOL    __cdecl EtsSetInterruptHandler(unsigned IntNumber,
               PETSINTHANDLER pHandler);

Ich verstehe da das genau Vorgehen nicht.
Was geschieht bei diesem Funktionsaufruf genau:
>>EtsSetInterruptHandler( UartIntVecNum, CommIntHandler);
Ist der CommIntHandler ein Zeiger auf einen bestimmten STACK?
Persönliche Seite #546856
Lesenswert?

Was auch immer das da sein soll, das hat nach wie vor nichts mit der 
UART zu tun.

Warum im Interrupthandler der Interruptcontroller befummelt wird, 
entzieht sich meinem Verständnis; die übliche Vorgehensweise in einem 
PC-Interrupthandler (unter DOS, also praktisch ohne Betriebssystem) 
sieht so aus:

[int]

Schnittstellenstatus aus UART auslesen
(Warum hat die UART den Interrupt ausgelöst?)

Je nach Schnittstellenstatus zu erledigende Dinge tun
(Zeichen abholen und speichern oder Zeichen aus Sendepuffer lesen und an 
UART übertragen oder ...)

Interruptcontroller die Beendigung der Interruptroutine mitteilen

[reti]


Es ist nicht erforderlich, in der Interruptroutine irgendwelche 
Interruptvektoren zu bestimmen, denn das geschieht schon implizit durch 
Aufruf der richtigen Interruptroutine.
Persönliche Seite #546879
Lesenswert?

Dann darf das aber nicht mit dem Namen der Interruptroutine beschriftet 
sein.

Im übrigen wird auf PC-Hardware (unter DOS, also ohne Betriebssystem) 
ein Interrupthandler dadurch installiert, daß seine Startadresse in die 
Interrupttabelle im Arbeitsspeicher eingetragen wird. Danach muss nur 
noch dem Interruptcontroller mitgeteilt werden, daß es den 
Interrupthandler gibt (setzen/löschen des erforderlichen Bits) und 
fertig.


Hier mal etwas Pascal-Quelltext:

Interrupthandler
1
procedure v24_irq;
2
{ interruptroutine. Wird fr jedes auf 8250 ankommendes Zeichen aufgerufen }
3
interrupt;
4
  var
5
    zeichen : byte;
6
    inhalt : integer;
7
  begin
8
    inline($FA);              { Interrupts sperren }
9
    zeichen := port[uart];    { angekommenes Zeichen lesen }
10
    buffer[ein] := zeichen;   { Zeichen in FIFO eintragen }
11
    inc(ein);                 { Schreibzeiger erh”hen }
12
    inc(counter);             { Fllstand erh”hen }
13
    if (fifo_len - ein = 0)   { FIFO-Wraparound }
14
      then ein := 0;
15
    if (counter > fifo_len - fifo_dlost)
16
      then begin
17
        dec(counter);
18
        dec(ein);             { FIFO-šberlauf ! (weitere Zeichen ignorieren) }
19
      end;
20
    if (counter > fifo_len - fifo_off)
21
      then v24_off;           { Handshake : Schnittstelle abschalten }
22
    if (ein >= aus)
23
      then inhalt := ein - aus
24
      else inhalt := fifo_len - (aus - ein);
25
    counter := inhalt;
26
    inline($FB);              { Interrupts wieder zulassen }
27
    port[$20] := EOI;         { weitere Interrupts zulassen (8259) }
28
  end;
Die letzte Anweisung ist hier interessant.


Und hier wird der Interruptvektor gesetzt:
1
    { Interruptvektor retten & setzen }
2
    case com_intr[nr] of
3
      3 :
4
        begin
5
          setintvec(11,@v24_irq);
6
        end;
7
      4 :
8
        begin
9
          setintvec(12,@v24_irq);
10
        end;
11
      end;

Hier wird dem Interruptcontroller das Vorhandensein des Handlers 
mitgeteilt
1
          case com_intr[com_nr] of
2
            3 : port[interrupt_controller] := port_21 and $f7;
3
            4 : port[interrupt_controller] := port_21 and $ef;
4
          end;
5
          port[uart + 1] := 1;    { IRQ bei Datenempfang }
(sowie bei der UART der Empfangsinterrupt freigeschaltet


Die eigentliche Initialisierung der UART geschieht hier:
1
    { Baudratenteiler berechnen }
2
    baudteil := 115200 div baudrate;
3

4
    { Schnittstelle initialisieren }
5
    port[uart + 5] := 60;     { Line Status Register }
6
    port[uart + 1] := $00;    { Interrupt Enable Register }
7
    port[uart + 2] := $04;    { Interrupt Ident. Register }
8
    port[uart + 4] := $0B;    { Modem Control Register }
9
    port[uart + 3] := $80;    { Baudratenteiler ansprechen }
10
    port[uart] := lo(baudteil);
11
    port[uart + 1] := hi(baudteil);
12
    port[uart + 3] := $07;    { Line Control Register }

und ist natürlich vor dem Setzen und Initialisieren des 
Interrupthandlers durchzuführen.


Auch wenn das Turbo-Pascal-Code ist, lässt sich das recht leicht auch in 
C ausdrücken.


Was Du da gepostet hast, hat mit irgendeinem Betriebssystem oder 
irgendeiner betriebssystemartigen Umgebung zu tun.
Gast #546892
Lesenswert?

Danke für die Hilfe!!!
Ich habe es jetzt mal so in Sätzen zusammengefasst:

Das Senden und Empfangen von der seriellen Schnittstelle funktioniert 
hier Interruptgesteuert. Dazu wurde ein Interrupt Handler eingerichtet, 
in diesem wird das Interrupt Identifikations Register ausgelesen. Über 
das Interrupt Identifikations Register, erfährt der Interrupt 
Controller, wegen welchem Ereignis der Interrupt ausgelöst wurde. Der 
Interrupt Handler wird dadurch installiert, dass seine Startadresse in 
die Interrupttabelle im Arbeitsspeicher eingetragen wird. Danach wird 
noch dem Interrupt Controller mitgeteilt, dass der Interrupt Handler 
existiert.

Sobald der UART ein Datum empfängt bzw. ein Datum an die UART übergibt, 
wird ein Interrupt ausgelöst, dieser veranlasst, dass der Interrupt 
Handler gestartet wird.

(Auf dem Board läuft ein 32Bit Echtzeitbetriebssystem, dort kann man auf 
die Win API zugreifen)
Persönliche Seite #546898
Lesenswert?

> Über das Interrupt Identifikations Register, erfährt der Interrupt
> Controller, wegen welchem Ereignis der Interrupt ausgelöst wurde.

Nein. Der Interrupt-Controller hat damit nichts zu tun, durch das 
Auslesen des IIR erfährt der Interrupt-Handler (also Deine Software), 
welches Ereignis den Interrupt ausgelöst hat.

Wann der/die UART Interrupts auslöst, wird durch die Initialisierung 
festgelegt, dort lassen sich Interrupts bei Datenempfang, leerem 
Senderegister, Änderungen der Handshakeleitungen etc. konfigurieren.

Da Du aber ein Betriebssystem verwendest, werden etliche Details anders 
gehandhabt werden; das Betriebssystem selbst verwaltet die Behandlung 
des Interruptcontrollers und auch das Einrichten eines Interrupthandlers 
durch entsprechende Funktionsaufrufe.

Daher sind die in den von mir geposteten Pascal-Sourcen getätigten Dinge 
nur mit äußerster Vorsicht zu genießen.

Ist das 32-Bit-Echtzeitsystem zufälligerweise OnTime RTOS-32?
Gast #546912
Lesenswert?

>Ich habe es jetzt mal so in Sätzen zusammengefasst:
Schön aber was soll das?

>Das Senden und Empfangen von der seriellen Schnittstelle funktioniert
>hier Interruptgesteuert...
Brauchst du das für einen Vortrag oder willst du irgendwas 
programmieren?
Wie das mit den Interrupts funktioniert wissen zumindest die die dir 
helfen könnten. Es ist nur unklar was du eigentlich willst.

>Sobald der UART ein Datum empfängt bzw. ein Datum an die UART übergibt,
>wird ein Interrupt ausgelöst, dieser veranlasst, dass der Interrupt
>Handler gestartet wird.
nicht ganz der 16c550 kann auch erst bei einem bestimmten Füllstand 
Interrupts auslösen. Also wenn mehrere Daten vorhanden sind.

>(Auf dem Board läuft ein 32Bit Echtzeitbetriebssystem, dort kann man auf
>die Win API zugreifen)
Die erste richtige Info, wie heißt das Betriebssystem und was willst du 
eigentlich machen?
Gast #546922
Lesenswert?

Als Betriebssoftware wird die ETS -  TNT Embedded ToolSuite von PharLap 
eingesetzt. Diese ist ein 32 bit Real-Time Operating System (RTOS), das 
sich durch Unterstützung eines Teils der WIN32 API leicht in Windows 
Systeme integrieren lässt.

Ich möchte eigentlich den ganzen Vorgang von der seriellen Kommunikation 
(UART) dokumentieren. Mein Programm benutzt ein Interrupt Handler für 
die serielle Schnittstelle.

1. Beschreibung UART
2. Initialiserung UART
3. Aktivierung Interrupt für COM
4. Erstellung eines Interrupt Handlers für COM
5. Funktionsweise des Interrupt Handlers
Gast #546954
Lesenswert?

Ich hab nochmals meinen Text einwenig verändert:

Das Senden und Empfangen von der seriellen Schnittstelle funktioniert 
hier Interruptgesteuert. Dazu wurde ein Interrupt Handler eingerichtet, 
in diesem wird das Interrupt Identifikations Register ausgelesen. Über 
das Auslesen des Interrupt Identifikations Registers, erfährt der 
Interrupt Handler, welches Ereignis den Interrupt ausgelöst hat. Der 
Interrupt Handler wird dadurch installiert, indem seine Startadresse in 
die Interrupttabelle im Arbeitsspeicher eingetragen wird. Danach wird 
dem Interrupt Controller mitgeteilt, dass der Interrupt Handler 
existiert.

Sobald der UART ein Datum empfängt bzw. ein Datum an die UART übergibt, 
wird ein Interrupt ausgelöst, dieser veranlasst, dass der Interrupt 
Handler gestartet wird.

(Dies soll eigentlich einfach gehalten werden)
Persönliche Seite #546987
Lesenswert?

> Fakt ist, das ist ein  ein 32 bit Real-Time Operating System (RTOS).
> Dieses Programmiere ich mit Visual Studio 6.0 (C++).

Du wirst unglaubwürdig, da Du zwei unterschiedliche Produkte aufgeführt 
hast. Würdest Du tatsächlich mit einem davon arbeiten, wüsstest Du, wie 
es heißt.

Trotzreaktionen sind hier wenig hilfreich.

> > Ich programmiere unter Linux.
>
> > Ich programmiere unter Windows.
>
> Was denn nun?
>
> > Fakt ist, das ist ein 32-Bit Betriebssystem.

Erkennst Du Deine "Argumentation" wieder?

Sei's drum.


> Sobald der UART ein Datum empfängt bzw. ein Datum an die UART übergibt,

Den Sendeinterrupt (TXEMPT) solltest Du besser anders beschreiben.

Sobald der UART ein in sein Senderegister geschriebenes Zeichen (trenne 
Dich vom unglücklichen "Datum"!) versendet hat, wird der "transmit 
register empty"-Interrupt ausgelöst, um zu signalisieren, daß ein neues 
Zeichen versendet werden kann.
Persönliche Seite #547000
Lesenswert?

Ich habe bereits dargelegt, daß es einen ganz erheblichen Unterschied 
macht, worunter/wofür man einen Interrupthandler schreibt - es ist was 
anderes, ob man einen Interrupthandler für RTOS-32 (das ist ein Produkt! 
Keine generische Bezeichnung) oder für Pharlap TNT ETS schreibt.

Der Windows-/Linux-Vergleich ist eine Metapher für Deine Reaktion auf 
die Frage, wofür Du da was zu schreiben glaubst.

Das Handling des ganzen Geraffels ist eben unterschiedlich und 
deswegen kommt es darauf an, die Rahmenbedingungen zu kennen und auch zu 
nennen.

Dir aber scheint es wohl nur um einen Aufsatz oder dergleichen zu gehen 
...
Gast #547007
Lesenswert?

Ich habs jetzt so geschrieben:

Sobald der UART ein in seinem Senderegister geschriebenes Zeichen 
versendet hat, wird „transmit holding register empty“- Interrupt 
ausgelöst, um zu signalisieren, dass ein neues Zeichen versendet werden 
kann. Im umgekehrten Fall, wenn ein Zeichen im Empfangsregister 
vorliegt, dann wird „receive data is available“- Interrupt ausgelöst, 
damit wird signalisiert dass ein neues Zeichen empfangen werden kann.
Gast #547011
Lesenswert?

Ich habe eher das Gefühl, du machst einen Teil einer Belegarbeit an der 
Uni,
die anderen haben es programmiert und da du Probleme dabei hattest, hast 
du dir den Dokumentationsteil rausgesucht.
Wenns wirklich so sein sollte: Schlechte Wahl, das setzt nämlich erst 
recht voraus, daß du alles verstehst.
Deine Bezeichnungen lassen erkennen, daß du in Hardwarenaher 
Programmierung nicht firm bist.

>Ich habs jetzt so geschrieben:
>...
ist etwas besser, aber deutlicher wird es mit einem Statediagram und 
Text

>dann wird „receive data is available“- Interrupt ausgelöst,
>damit wird signalisiert dass ein neues Zeichen empfangen werden kann.
das ist Müll, wenn du ein Zeichen bekommst solltest du es abholen
Gast #547543
Lesenswert?

Ich hoffe das stimmt was ich hier geschrieben habe:

Das Senden und Empfangen von der seriellen Schnittstelle funktioniert 
hier Interruptgesteuert. Dazu wurde ein Interrupt Handler eingerichtet, 
in diesem wird das Interrupt Status Register ausgelesen. Über das 
Auslesen des Interrupt Status Registers, erfährt der Interrupt Handler, 
welches Ereignis den Interrupt ausgelöst hat.

Der Interrupt Handler wird dadurch installiert, indem seine Startadresse 
in die Interrupttabelle im Arbeitsspeicher eingetragen wird. Danach wird 
dem Interrupt Controller mitgeteilt, dass der Interrupt Handler 
existiert.

Sobald der UART ein in seinem Senderegister geschriebenes Zeichen 
versendet hat, wird „transmit holding register empty“- Interrupt 
ausgelöst, um zu signalisieren, dass ein neues Zeichen versendet werden 
kann. Im umgekehrten Fall, wenn ein Zeichen im Empfangsregister 
vorliegt, wird „receive data is available“- Interrupt ausgelöst, damit 
kann nun das Zeichen vom Empfangsregister abgeholt werden.
Gast #547873
Lesenswert?

> Danach wird dem Interrupt Controller mitgeteilt, dass der Interrupt
> Handler existiert.

Ich weiß ja nicht was da für ein Interruptcontroller drauf ist aber 
normalerweise wird der betreffende Interrupt nur freigeschaltet.
Gast #550150
Lesenswert?

Es ist ein 8259 Controller. Der kann doch 15 Geräte verwllten oder?

void __cdecl CommIntHandler(ETSINTREGS *pRegs);

void COM(void)
{
 ...
 UartIntVecNum = EtsPicGetIRQIntNumber(UartIRQNum);
 // --> UartIntVecNum = 0x0C
 ....
 EtsSetInterruptHandler( UartIntVecNum, CommIntHandler); // set handler
 ...
}

Ich hab da noch immer Probleme damit. Ich beschreibe es mal mit meinen 
eigenen Worten.
1. UartIntVecNum = EtsPicGetIRQIntNumber(UartIRQNum);
--> Nr. von der Vectortabelle auslesen, ist hier 0x0C
  (Warum Vectortabelle?)
2.EtsSetInterruptHandler( UartIntVecNum, CommIntHandler); // set handler
--> Interrupt Handler einrichten: 0x0C und Adresse vom Interrupt Handler 
der Funktion übergeben. Dann passiert irgendwas im Stack.

Weiss nicht so ganz obn dies hier stimmt.
Gast #550614
Lesenswert?

Ein 8259 kann 8 Interrupts verwalten - man kann ihn aber auch 
kaskadieren und bekommt dann Weitere.

Wie ein Interrupt abläuft:

Byte wurde empfangen -> UART akiviert die IRQ-Leitung -> IRQController 
prüft, ob aktiviert -> IRQController aktiviert die INT-Leitung zum 
Prozessor -> wenn Interrupts dort freigeschaltet sind: Prozessor macht 
seinen aktuellen Befehl noch fertig, schreibt die aktuelle CS:IP Adresse 
auf den Stack und setzt die INTA-Leitung zum IRQController -> 
IRQController überträgt den Vector (Vectortabelle ist ein Array mit den 
Anfangsaddressen der Interrupthandler-Funktionen, Vector der Index eines 
Eintrages in dieser Tabelle) -> CPU springt die zum Vector passende 
Interrupthandler-Funktion an -> Interrupthandler fragt die Hardware ab 
-> UART deaktiviert seine IRQ-Leitung -> Interrupthandler macht ein IRET 
(oder wars RETI?) -> CPU macht da weiter wo sie unterbrochen wurde.
Gast #558462
Lesenswert?

Guten Abend, ich habe doch noch Probleme mit dem Interrupt Handler.
Und zwar es wird doch zuerst die Vectornummer von der Schnittstelle COM1 
(0x3F8) ausgelesen. Dies ist hier 0x0C. Dann wirdn doch der eigentliche 
Interrupt Handler installiert bzw. eingerichtet. Die Funktion 
EtsSetInterrupt Handler erhält zwei Parameter. 1. Parameter = 
Vectornummer 0x0C, 2. Parameter  die Adresse vom Interrupt Handler. Ist 
das jetzt richtig so?
Ich möchte nur diesen Vorgang beschreiben. Mir ist nun nicht ganz klar 
ob meine Aussage so stimmt.
1
void __cdecl CommIntHandler(ETSINTREGS *pRegs);
2

3
void COM(void)
4
{
5
...
6
UartIntVecNum = EtsPicGetIRQIntNumber(UartIRQNum); 
7
...
8
EtsSetInterruptHandler( UartIntVecNum, CommIntHandler); // set handler
9
...
10
}
Gast #558748
Lesenswert?

2F8 und 3F8 sind IO adressen, wo das UART montiert ist. Was soll das 
Ganze ? Weder unter Linux, noch unter Windows schreibt jemand einen 
Interrupthandler.  Dort ist die Thematik eine ganz andere. Wie 
manoevriert man in den Tiefen des verbockten Windows, ohne das alles 
abschmiert. Sogar kundige Spzialisten verbraten da schnell mal 2 Monate. 
Vergiss es.
Intel hat einen schoenen Interruptcontroller gemacht, der kann 
Prioritaeten zuweisen und rotieren. Trotzdem wollte Microsoft was 
anderes und hat oben eine Software draufgesetzt die alles vermurkst.
Als Einsteigelektuere sei das iAPX86 Manual von Intel empfohlen, Dort 
wird auch der 8259 beschrieben, und ein paar Interrupthandler sind da 
auch drin. Als naechstes waere das 386 Manual mit dem Protected mode 
empfohlen. Dort wurden die Interrupts virtualisiert und muessen durch 
trap gates. Seither hat sich interruptmaessig nicht mehr sehr viel fuer 
den Benutzer geaendert.
Gast #558771
Lesenswert?

Das ist ein Webserverboard von PharLap. Es nutzt ETS ein 32 bit Echtzeit 
Betriebssystem und kann ein Teil der WIN32 API-Funktionen. Der Prozessor 
ist ein AMD-ELAN Prozessor mit 66 MHZ. Programmieren tue ich das ganze 
unter Visual Studio 6.0 mit C++.
Gast #558819
Lesenswert?

Ich habe die Beschreibungen zu dem entsprechenden Funktionen gefunden.
Ich hab da Probleme das ganze hier zu verstehen.

//
// Return the interrupt vector number which corresponds to the
// specified hardware IRQ.  Assumes PC/AT mapping of 08h for IRQs 0-7
// and 70h for IRQs 8-15.  Source is provided in 
PHAREMB/EMBCUST/PCPIC.ASM.
//
// hardwareIRQNum is the desired IRQ number
//
// Returns the interrupt vector number which corresponds to the
// specified IRQ, or -1 if the specified IRQ is out of range.
//
int     __cdecl EtsPicGetIRQIntNumber(int hardwareIRQNum);


//---------------------------------------------------------------------- 
-------
// EtsSetInterruptHandler - Install a C function as an interrupt handler
//
//      This API installs a C function as an interrupt handler
//      for the specified interrupt.  The handler is entered as a normal
//      C function (__cdecl calling sequence) with interrupts disabled
//      and receives a pointer to the saved register set on the stack
//      as its argument.  The saved register set includes all general
//      purpose registers, DS, ES, and EFLAGS.  The FS and GS registers
//      are neither saved nor restored; if the handler alters them, it
//      must restore them itself before returning.  The handler
//      is expected to process the interrupt and may modify the
//      saved register set on the stack if wishes to
//      alter the context of the interrupted code.  When the handler 
// function
//      returns, the saved registers are popped off the stack and
//      control returns to the interrupted code.
//
//      The return value from the function is TRUE if successful or 
FALSE
//      if an error occurs.
//
//---------------------------------------------------------------------- 
-------
BOOL    __cdecl EtsSetInterruptHandler(unsigned IntNumber,
               PETSINTHANDLER pHandler);

//
// Saved register block passed to interrupt handlers registered
// with EtsSetInterruptHandler() and EtsSetExceptionHandler().
// These fields contain the register contents at the time of the
// interrupt.  The interrupt service routine can modify the
// values in the passed structure in order to change the user
// registers on return from the interrupt.
//
// Note:  The FS and GS registers are neither saved nor restored
// by the interrupt handler framework.  If a user interrupt handler
// wants to use either of these registers, it must preserve them itself!
//
typedef struct tagETSINTREGS
{
  DWORD   Ebp;                    // [00]
  DWORD   Eax;                    // [04]
  DWORD   Ebx;                    // [08]
  DWORD   Ecx;                    // [12]
  DWORD   Edx;                    // [16]
  DWORD   Esi;                    // [20]
  DWORD   Edi;                    // [24]
  DWORD   Gs;                     // [28]
  DWORD   Ds;                     // [32]
  DWORD   Es;                     // [36]
  DWORD   IntNum;                 // [40]
  DWORD   Ecode;                  // [44]   (Zero if int w/o error code)
  DWORD   Eip;                    // [48]
  DWORD   Cs;                     // [52]
  DWORD   Eflags;                 // [56]
} ETSINTREGS, *PETSINTREGS;

void __cdecl CommIntHandler(ETSINTREGS *pRegs);

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren