From: boylesgj AT lion DOT cs DOT latrobe DOT edu DOT au (Gregary J Boyles) Newsgroups: comp.os.msdos.djgpp Subject: Inline assembly instead of ISR wrappers. Date: 8 May 1997 12:35:35 GMT Organization: Comp.Sci & Comp.Eng, La Trobe Uni, Australia Lines: 315 Distribution: world Message-ID: <5kshan$mlc@lion.cs.latrobe.edu.au> NNTP-Posting-Host: lion.cs.latrobe.edu.au To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Precedence: bulk I am trying to develop a series of macros to use in and around and ISR instead of having to use wrappers. I might be on to something here because this macro system for setting up ISR's seems to more or less work. It would be bloody fantastic if you could piss the wrappers off all together. It seems to crash some where in ISR_EXIT and I am not sure where. Can any body pick it? The other problem is local variables. They would be allocated on the old stack which means referencing them after changing the stack will cause catastrophy. I can see two solutions. Don't use local variables or some how transfer them to the new stack. Is that possible? // Macro for setting up a variable which contains the DJGPP data segment. #define MAKE_DJGPP_DS short unsigned int DJGPPDataSegment=_go32_my_ds() #define GET_DJGPP_DS DJGPPDataSegment // Macro for setting up an ISR stack. #define MAKE_ISR_STACK(ISRName) const long unsigned int StackSize##ISRName=1024*100;\ char Stack##ISRName[StackSize##ISRName] #define GET_ISR_STACK(ISRName) Stack##ISRName #define GET_ISR_STACK_SIZE(ISRName) StackSize##ISRName // Macros for setting ISR entry and exit code. #define ISR_ENTRY(ISRStack,ISRStackSize,DJGPPDataSegment)\ asm volatile("\npopl %%bp\n"\ "pushal\n"\ "pushw %%ds\n"\ "pushw %%es\n"\ "pushw %%fs\n"\ "pushw %%gs\n"\ "movw %2,%%ax\n"\ "movw %%ax,%%ds\n"\ "movw %%ax,%%es\n"\ "movw %%ax,%%fs\n"\ "movw %%ax,%%gs\n"\ "movw %%ss,%%bx\n"\ "movl %%esp,%%ecx\n"\ "movw %%ax,%%ss\n"\ "movl %0,%%sp\n"\ "addl %1,%%sp\n"\ "pushw %%bx\n"\ "pushl %%ecx\n"\ "pushl %%bp\n"\ "movl %%sp,%%bp\n"\ :\ :"g"(ISRStack),"g"(ISRStackSize),"g"(DJGPPDataSegment)\ ) #define ISR_EXIT\ asm volatile("\npopl %bp\n"\ "popl %ecx\n"\ "popw %bx\n"\ "movw %bx,%ss\n"\ "movl %ecx,%esp\n"\ "popw %gs\n"\ "popw %fs\n"\ "popw %es\n"\ "popw %ds\n"\ "popal\n"\ "sti\n"\ "iret\n"\ ) unsigned char ScanCode=0; EventC Event; MAKE_ISR_STACK(KeyBoardISR); MAKE_DJGPP_DS; void KeyBoardISR(...) { ISR_ENTRY(GET_ISR_STACK(KeyBoardISR),GET_ISR_STACK_SIZE(KeyBoardISR),GET_DJGPP_DS); ScanCode=ISRTools.GetScanCode(); // Update the flags. switch (ScanCode) { case 56 : ISRTools.AltInc();break; case 184 : ISRTools.AltDec();break; case 29 : ISRTools.CtrlInc();break; case 157 : ISRTools.CtrlDec();break; case 54 : ISRTools.ShiftInc();break; case 42 : ISRTools.ShiftInc();break; case 182 : ISRTools.ShiftDec();break; case 170 : ISRTools.ShiftDec();break; case 58 : ISRTools.ToggleCapsLock();break; case 69 : ISRTools.ToggleNumLock();break; case 70 : ISRTools.ToggleScrollLock();break; case 224 : if (!ISRTools.IsExtendedKey()) ISRTools.ToggleExtendedKey(); break; case 225 : if (!ISRTools.IsSpecialExtendedKey()) ISRTools.ToggleSpecialExtendedKey(); break; }; // Update the LED's ISRTools.UpdateLEDs(); // This is a key board event. Event.Type=KeyBoard; Event.MouseX=Event.MouseY=0; Event.MouseKey=Left; // Copy the status of the state shift keys into the event. Event.Alt=ISRTools.IsAltOn(); Event.Ctrl=ISRTools.IsCtrlOn(); Event.Shift=ISRTools.IsShiftOn(); Event.CapsLock=ISRTools.IsCapsLockOn(); Event.NumLock=ISRTools.IsNumLockOn(); Event.ScrollLock=ISRTools.IsScrollLockOn(); // Time stamp the event. TimeS Time; GetTime(Time); Event.Time.Set(Time.Hour,Time.Minute,Time.Second,Time.Second100); // Break key handling. // // Scan codes sent when key is pressed alone // ----------------------------------------- // 225,29,69,225,157,197 // // Scan codes sent when key is pressed and released with ctrl key held // ------------------------------------------------------------------- // 224,70,224,198 if ((ISRTools.IsSpecialExtendedKey() && ((ScanCode==29) || (ScanCode==69) || (ScanCode==157) || (ScanCode==197))) || (ISRTools.IsExtendedKey() && ((ScanCode==70) || (ScanCode==198)))) { // If CtrlBreak was pressed and CtrlBreak handling is on then call the // DOS handler. if ((ScanCode==70) && ISRTools.IsCtrlBreakHandOn()) { } // Otherwise we want to queue the key press or release. // // Since multiple scan codes are sent we need to ignore some of them otherwise // we will end up queueing multiple key presses even though it was pressed // once. // // Hence we will acknowledge the scan code 29 (when the break key is pressed // alone) and the the scan code 70 (when the break key is pressed with the // ctrl key held. In both case we will identify the key with the scan code // 224+70=294. else if ((ScanCode==29) || (ScanCode==157) || (ScanCode==70) || (ScanCode==198)) { Event.ScanCode=224+70; Event.ASCII=0; if ((ScanCode & 0x80) > 0) Event.What=Released; else Event.What=Pressed; EventQueue.Enqueue(Event); } // If the last scan code has been sent then turn off the SpecialExtendedKey // ExtendedKey flags off. if (ScanCode==187) ISRTools.ToggleSpecialExtendedKey(); else if (ScanCode==198) ISRTools.ToggleExtendedKey(); } // Print screen/system request handling. // // Scan codes sent when key is pressed and released // ------------------------------------------------ // 224,42,224,55,224,170,224,183 // // Scan codes sent when key is pressed and released with shift or ctrl keys held // ----------------------------------------------------------------------------- // 224,55,224,183 // // Scan codes sent when key is pressed and released with alt key held // ------------------------------------------------------------------ // 84,212 else if ((ISRTools.IsExtendedKey() && ((ScanCode==42) || (ScanCode==55) || (ScanCode==170) || (ScanCode==183))) || (ISRTools.IsExtendedKey() && ((ScanCode==55) || (ScanCode==183))) || (ScanCode==84) || (ScanCode==212)) { // If PrntScn was pressed and PrntScn handling is on then call the // DOS handler. if ((ScanCode==42) && ISRTools.IsCtrlBreakHandOn()) { } // Otherwise we want to queue the key press or release. // // Since multiple scan codes are sent we need to ignore some of them otherwise // we will end up queueing multiple key presses even though it was pressed // once. // // Hence we will acknowledge the scan code 55 (when the prntscn key is // pressed alone), the the scan code 55 (when the prntscn key is pressed // with a ctrl or shift key held and scan code 84 (when the prntscn key is // pressed with the alt key held). In both case we will identify the key // with the scan code 224+84=308. else if ((ScanCode==55) || (ScanCode==183) || (ScanCode==84) || (ScanCode==212)) { Event.ScanCode=224+84; Event.ASCII=0; if ((ScanCode & 0x80) > 0) Event.What=Released; else Event.What=Pressed; EventQueue.Enqueue(Event); } // If the last scan code has been sent then turn off the ExtendedKey flag // off. if (ISRTools.IsExtendedKey() && (ScanCode==183)) ISRTools.ToggleExtendedKey(); } // CtrlAltDel handling. else if (ISRTools.IsCtrlOn() && ISRTools.IsAltOn() && ((ScanCode==83) || (ScanCode==211))) { // If CtrlAltDel was pressed and CtrlAltDel handling is on then call the // DOS handler. if (ISRTools.IsCtrlAltDelHandOn()) { } // Otherwise just queue the key press or release. else { Event.ScanCode=83; Event.ASCII=0; if ((ScanCode & 0x80) > 0) Event.What=Released; else Event.What=Pressed; EventQueue.Enqueue(Event); } } // Trap extended codes. else if ((ScanCode==224) || (ScanCode==225)) { } // We want to distinguish right ctrl and alt from left ctrl and alt. The // former are extended keys while the latter are not. We will do so by adding // 224 to their scan codes. // Extended keys send the extended code 224 followed by their specific scan // code. else if (ISRTools.IsExtendedKey() && ((ScanCode==56) || (ScanCode==29))) { // Mask off the 7th bit and add 224. Event.ScanCode=224+(ScanCode & 0x7F); // If the 7th bit is set then the key was released. if ((ScanCode & 0x80) > 0) Event.What=Released; else Event.What=Pressed; EventQueue.Enqueue(Event); } else { // Mask out the 7th bit. Event.ScanCode=ScanCode & 0x7F; // Get the ASCII character for this key. Event.ASCII=ISRTools.GetASCII(Event.ScanCode); // If the 7th bit is set then the key was released. if ((ScanCode & 0x80) > 0) Event.What=Released; else Event.What=Pressed; EventQueue.Enqueue(Event); } ISRTools.AcknowledgeInterrupt(); ISR_EXIT; }