Date: Fri, 31 Oct 1997 02:02:08 +0000 ( ) From: "Gurunandan R. Bhat" To: djgpp AT delorie DOT com Subject: Tracing the path of Software Interrupts Message-Id: Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Precedence: bulk Greetings, I am trying to understand the details of interrupt handling in DJGPP. In this regard, I thought of writing a small program that would install both, protected and real mode interrupt handlers for the different kinds of interrupts (hardware and software) and trace the manner in which control is transferred from one to the other and also the order in which they are invoked. My protected mode handler writes a 'p' to an array whenever it is called and my real mode handler writes 'r' to the same array. The array is initialised with 'x'. I expect that the characters in the array would describe the order in which things happen. Of course, I did try to write 16 bit code for the real mode handler and copy it to conventional memory but it wouldn't work (I'm new to assembly, but I'm trying and hope to complete the 16 bit code soon) so I installed a real mode callback instead which would be slower but would, I hope tell the same story. I also plan to leave the handlers in different ways like iret, chain and far calls so that each method of leaving the handler would teach me the path of interrupt handling calls. When I do this for the software interrupt (0x1c) I get a result that to my **limited** understanding, is strange. It is always the real mode interrupt that is called. My buffer is strewn with 'r's. This is the same no matter which of the three DPMI hosts I use: cwsdpmi, cwsdpr0 or pmode/dj. But when I run the same program in Windows 3.11, I get an alternating string of 'p' and 'r' like: prprpr...., *even* when I do not chain out of the protected mode handler. Obviously I am doing something terribly WRONG! The DPMI specs say that int 0x1c is special in that, it is always handled by the protected mode handler *even* when a real mode handler is installed. Have I misunderstood something? Very likely! It could also be that my inexperience with GAS has finally taken its toll. However I did go through my code many times before I posted this. I am appending my main c (test.c) program below and than the gas module (my_isr.s) after that. My command line is simple: gcc -Wall test.c my_isr.s -otest.exe Would a kind Guru please help me understand this -------------------test.c------------------------------------------ #include #include #include #include extern int init_handlers(void); extern void reset_handlers(void); unsigned long buff_size = 0x10000; char *buffer; int main(void) { unsigned long i; int test; char curr_char; FILE *outfile; buffer = (char *) malloc(buff_size); if (!buffer) { printf("Unable to allocate buffer, Returning!\n"); return(1); } for(i = 0; i < buff_size; ++i) buffer[i] = 'x'; outfile = fopen("history.dat", "w"); if(_go32_dpmi_lock_data(&buff_size, 4) == -1) { printf("Unable to lock data (buff_size)! Returning\n"); return(1); } if(_go32_dpmi_lock_data(buffer, buff_size) == -1) { printf("Unable to lock data (buffer)!, Returning\n"); return(1); } init_handlers(); getch(); for(i = 0; i < 200 * buff_size; ++i) test = 2 * i - 4 * i; for(i = 0; i < buff_size; ++i) cprintf("%c\r", buffer[i]); for(i = 0; i < buff_size; ++i) { curr_char = buffer[i]; if (curr_char != 'x') fprintf(outfile, "Displaying buffer %lu .......%c\n", i, curr_char); } reset_handlers(); fclose(outfile); return(0); } ----------------------------my_isr.s----------------------------- .file "my_isr.s" .text .globl _init_handlers .globl _reset_handlers begin_code_region: pm_handler: pushfl .byte 0x2e movw ___djgpp_ds_alias, %ds movl index, %eax cmpl %eax, _buff_size jbe %cs:exit_pm_handler incl index addl _buffer, %eax movb $'p, (%eax) exit_pm_handler: popfl sti iret rm_handler: # set up real mode return address from contents of real mode stack movl (%esi), %eax movl %eax, %es:0x2a(%edi) movw 4(%esi), %ax movw %ax, %es:0x20(%edi) addw $6, %es:0x2e(%edi) # increment index if within buffer bounds pushw %ds .byte 0x2e movl ___djgpp_ds_alias, %ds movl index, %eax cmpl %eax, _buff_size jbe %cs:exit_rm_handler incl index addl _buffer, %eax movb $'r, (%eax) exit_rm_handler: popw %ds sti iret end_code_region: _init_handlers: pushl %ebp movl %esp, %ebp pushfl pushl %ebx pushl %ecx pushl %edx pushl %esi pushl %edi # lock code region movl $begin_code_region, %ecx movl $end_code_region, %edi subl %ecx, %edi addl ___djgpp_base_address, %ecx shldl $0x10, %ecx, %ebx shldl $0x10, %edi, %esi movw $0x0600, %ax int $0x31 movl $-1, %eax jc cleanup movl $1, %eax # lock data region movl $begin_data_region, %ecx movl $end_data_region, %edi subl %ecx, %edi addl ___djgpp_base_address, %ecx shldl $0x10, %ecx, %ebx shldl $0x10, %edi, %esi movw $0x0600, %ax int $0x31 movl $-1, %eax jc cleanup movl $1, %eax # save protected mode interrupt vector movw $0x0204, %ax movb $0x1c, %bl int $0x31 movw %cx, sel_orig_pm_handler movl %edx, off_orig_pm_handler # this function always succeeds # point protected mode handler to our own movw $0x0205, %ax pushw %cs popw %cx movl $pm_handler, %edx movb $0x1c, %bl int $0x31 movl $-1, %eax jc cleanup movl $1, %eax # allocate real mode callback movw $0x0303, %ax pushw %ds popw %es movl $dpmi_regs, %edi pushw %ds pushw %cs popw %ds movl $rm_handler, %esi int $0x31 popw %ds movl $-1, %eax jc cleanup movl $1, %eax movw %cx, seg_rmcb movw %dx, off_rmcb # save real mode interrupt vector movw $0x0200, %ax movb $0x1c, %bl int $0x31 movw %cx, seg_orig_rm_handler movw %dx, off_orig_rm_handler # this function always succeeds # point real mode interrupt vector to real mode callback movw $0x0201, %ax movb $0x1c, %bl movw seg_rmcb, %cx movw off_rmcb, %dx int $0x31 # this function always succeeds cleanup: popl %edi popl %esi popl %edx popl %ecx popl %ebx popfl movl %ebp, %esp popl %ebp ret _reset_handlers: # reset protected mode interrupt vector pushl %ebp movl %esp, %ebp pushfl pushl %ebx pushl %ecx pushl %edx movw $0x0205, %ax movb $0x1c, %bl movw sel_orig_pm_handler, %cx movl off_orig_pm_handler, %edx int $0x31 # reset real mode interrupt vector movw $0x0201, %ax movb $0x1c, %bl movw seg_orig_rm_handler, %cx movw off_orig_rm_handler, %dx int $0x31 # free real mode callback wrapper movw $0x0304, %ax movw seg_rmcb, %cx movw off_rmcb, %dx int $0x31 popl %edx popl %ecx popl %ebx popfl movl %ebp, %esp popl %ebp ret .data begin_data_region: index: .long 0 orig_pm_handler: off_orig_pm_handler: .long 0 sel_orig_pm_handler: .short 0 seg_orig_rm_handler: .short 0 off_orig_rm_handler: .short 0 seg_rmcb: .short 0 off_rmcb: .short 0 dpmi_regs: .fill 50, 1, 0 end_data_region: ---------------------------------------------------------------------