From: Paul Lay Newsgroups: comp.os.msdos.djgpp Subject: real mode int slower???? Date: Mon, 03 Feb 1997 11:49:33 +0000 Organization: Nortel Limited Lines: 295 Message-ID: <32F5D0CD.41C67EA6@nortel.co.uk> NNTP-Posting-Host: bhl3s9d.bnr.co.uk Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp I've just turned a protected mode interrupt into a real mode one, looking for a performance gain but instead things got worse... I'm using the timer interrupt (0x08) to read the joystick. What I do is increase the timer frequency to around 6kHz and install a new isr that monitors the joystick, building up its x and y positions (at this rate you get ranges of 0..9 for both x and y positions). In order to maintain the time of day and whatever else is done during the normal timer interrupt, I periodically chain to the old timer interrupt so that it's still invoked 18.2 times/sec. I originally did this using protected mode interrupts which worked fine, but it seemed slightly more expensive than when previously working in real mode under Borland. So I rewrote using real mode interrupts, but this has proved significantly more expensive. Below is my joystick code. Any ideas? Even though I've only installed a real mode isr, is it possible that there's still some protected mode isr processing being done? Cheers, Paul. /***************************************************************************/ /* Includes */ /***************************************************************************/ #include #include #include #include /***************************************************************************/ /* Constants */ /***************************************************************************/ #define TIMER_VECTOR (0x08) #define FILL (0x00) /***************************************************************************/ /* Global Variables */ /***************************************************************************/ int* joystickX; int* joystickY; int* joystickButtons; /***************************************************************************/ /* Local Variables */ /***************************************************************************/ static __dpmi_raddr oldVector; static __dpmi_raddr newVector; static int joystickIsrSelector; /***************************************************************************/ /* */ /* joystickIsr */ /* */ /* This code is copied into dos memory and configured as the real mode */ /* timer isr. The bytes marked FILL are overwritten during installation: */ /* the 2 bytes at offset 0x05 are set to the dos memory segment (where */ /* this code is located), the 4 bytes at offset 0x72 are set to the */ /* segment:offset of the old real mode timer isr. */ /* */ /***************************************************************************/ static char joystickIsr[] = { /* 0000 */ 0x50, /* push ax */ /* 0001 */ 0x52, /* push dx */ /* 0002 */ 0x1E, /* push ds */ /* 0003 */ 0x55, /* push bp */ /* 0004 */ 0xBD, FILL, FILL, /* mov bp,SEGMENT */ /* 0007 */ 0x8E, 0xDD, /* mov ds,bp */ /* 0009 */ 0xFF, 0x06, 0x70, 0x00, /* inc word ptr TIMECOUNT */ /* 000D */ 0x81, 0x3E, /* cmp word ptr TIMECOUNT,0x0155 */ 0x70, 0x00, 0x55, 0x01, /* 0013 */ 0x75, 0x10, /* jne L1 */ /* 0015 */ 0xC7, 0x06, /* mov word ptr TIMECOUNT,0x0000 */ 0x70, 0x00, 0x00, 0x00, /* 001B */ 0x9C, /* pushf */ /* 001C */ 0xFF, 0x1E, 0x72, 0x00, /* call dword ptr OLDHANDLER */ /* 0020 */ 0x5D, /* pop bp */ /* 0021 */ 0x1F, /* pop ds */ /* 0022 */ 0x5A, /* pop dx */ /* 0023 */ 0x58, /* pop ax */ /* 0024 */ 0xCF, /* iret */ /* 0025 */ 0xBA, 0x01, 0x02, /* L1: mov dx,0x0201 */ /* 0028 */ 0xEC, /* in al,dx */ /* 0029 */ 0xA8, 0x03, /* test al,0x03 */ /* 002B */ 0x75, 0x2A, /* jne L2 */ /* 002D */ 0xF6, 0xD0, /* not al */ /* 002F */ 0x24, 0x30, /* and al,0x30 */ /* 0031 */ 0xC0, 0xE8, 0x04, /* shr al,0x04 */ /* 0034 */ 0xA2, 0x80, 0x00, /* mov byte ptr JOYBUTTONS,al */ /* 0037 */ 0xA0, 0x76, 0x00, /* mov al,byte ptr XCOUNT */ /* 003A */ 0xA2, 0x78, 0x00, /* mov byte ptr JOYX,al */ /* 003D */ 0xA0, 0x77, 0x00, /* mov al,byte ptr YCOUNT */ /* 0040 */ 0xA2, 0x7C, 0x00, /* mov byte ptr JOYY,al */ /* 0043 */ 0xC6, 0x06, /* mov byte ptr XCOUNT,0x00 */ 0x76, 0x00, 0x00, /* 0048 */ 0xC6, 0x06, /* mov byte ptr YCOUNT,0x00 */ 0x77, 0x00, 0x00, /* 004D */ 0xEE, /* out dx,al */ /* 004E */ 0xB0, 0x20, /* mov al,0x20 */ /* 0050 */ 0xE6, 0x20, /* out 0x20,al */ /* 0052 */ 0x5D, /* pop bp */ /* 0053 */ 0x1F, /* pop ds */ /* 0054 */ 0x5A, /* pop dx */ /* 0055 */ 0x58, /* pop ax */ /* 0056 */ 0xCF, /* iret */ /* 0057 */ 0xA8, 0x01, /* L2: test al,0x01 */ /* 0059 */ 0x74, 0x04, /* je L3 */ /* 005B */ 0xFE, 0x06, 0x76, 0x00, /* inc byte ptr XCOUNT */ /* 005F */ 0xA8, 0x02, /* L3: test al,0x02 */ /* 0061 */ 0x74, 0x04, /* je L4 */ /* 0063 */ 0xFE, 0x06, 0x77, 0x00, /* inc byte ptr YCOUNT */ /* 0067 */ 0xB0, 0x20, /* L4: mov al,0x20 */ /* 0069 */ 0xE6, 0x20, /* out 0x20,al */ /* 006B */ 0x5D, /* pop bp */ /* 006C */ 0x1F, /* pop ds */ /* 006D */ 0x5A, /* pop dx */ /* 006E */ 0x58, /* pop ax */ /* 006F */ 0xCF, /* iret */ /* 0070 */ 0x00, 0x00, /* TIMECOUNT: dc.w 0x0000 */ /* 0072 */ FILL, FILL, /* OLDHANDLER(offset): ds.w 1 */ /* 0074 */ FILL, FILL, /* OLDHANDLER(segment): ds.w 1 */ /* 0076 */ 0x00, /* XCOUNT: dc.b 0x00 */ /* 0077 */ 0x00, /* YCOUNT: dc.b 0x00 */ /* 0078 */ 0x04, 0x00, 0x00, 0x00, /* JOYX: dc.l 0x00000004 */ /* 007C */ 0x04, 0x00, 0x00, 0x00, /* JOYY: dc.l 0x00000004 */ /* 0080 */ 0x00, 0x00, 0x00, 0x00 /* JOYBUTTONS: dc.l 0x00000000 */ }; /***************************************************************************/ /* */ /* installJoystick */ /* */ /* Install joystickHandler and increase interrupt frequency. */ /* */ /***************************************************************************/ void installJoystick (void) { int numParagraphs; int segment; /* get current real mode timer isr */ if (__dpmi_get_real_mode_interrupt_vector (TIMER_VECTOR, &oldVector)) printf ("Error: unable to get real mode interrupt\n"); /* determine number of paragraphs for new isr */ numParagraphs = (sizeof (joystickIsr) + 15) >> 4; /* allocate dos memory for new isr */ segment = __dpmi_allocate_dos_memory (numParagraphs, &joystickIsrSelector); if (segment == -1) printf ("Error: unable to allocate dos memory\n"); /* set new isr's segment and old vector address */ *(short*)(joystickIsr + 0x05) = segment; *(short*)(joystickIsr + 0x72) = oldVector.offset16; *(short*)(joystickIsr + 0x74) = oldVector.segment; /* copy new isr into dos memory */ dosmemput (joystickIsr, sizeof (joystickIsr), segment << 4); /* configure new isr vector address */ newVector.offset16 = 0x0000; newVector.segment = segment; /* set new real mode timer isr */ if (__dpmi_set_real_mode_interrupt_vector (TIMER_VECTOR, &newVector)) printf ("Error: unable to set real mode interrupt\n"); /* set counter 0 to 6206.2 interrupts/sec */ asm ("cli"); asm ("movb $0x36,%al"); asm ("outb %al,$0x43"); asm ("movb $0xC0,%al"); asm ("outb %al,$0x40"); asm ("movb $0x00,%al"); asm ("outb %al,$0x40"); asm ("sti"); /* configure protected mode pointers to real mode data (must have previously enabled near pointers) - i.e. joystickX points to JOYX, joystickY to JOYY and joystickButtons to JOYBUTTONS */ joystickX = (int*)(__djgpp_conventional_base + (segment << 4) + 0x78); joystickY = (int*)(__djgpp_conventional_base + (segment << 4) + 0x7C); joystickButtons = (int*)(__djgpp_conventional_base + (segment << 4) + 0x80); } /***************************************************************************/ /* */ /* removeJoystick */ /* */ /* Restore interrupt frequency and old interrupt handler. */ /* */ /***************************************************************************/ void removeJoystick (void) { /* set counter 0 to 18.2 interrupts/sec */ asm ("cli"); asm ("movb $0x36,%al"); asm ("outb %al,$0x43"); asm ("movb $0x00,%al"); asm ("outb %al,$0x40"); asm ("movb $0x00,%al"); asm ("outb %al,$0x40"); asm ("sti"); /* restore original real mode timer isr */ if (__dpmi_set_real_mode_interrupt_vector (TIMER_VECTOR, &oldVector)) printf ("Error: unable to set real mode interrupt\n"); /* free dos memory allocated for new isr */ if (__dpmi_free_dos_memory (joystickIsrSelector)) printf ("Error: unable to free dos memory\n"); } /***************************************************************************/ /* */ /* This only shows how the above are used - you can't judge performance */ /* from this! */ /* */ /***************************************************************************/ void main (void) { if (!__djgpp_nearptr_enable ()) printf ("Error: unable to enable near pointers\n"); installJoystick (); /* while no buttons pressed */ while (!*joystickButtons) { printf ("x = %x y = %x\n", *joystickX, *joystickY); } removeJoystick (); }