From: Jack Cai Newsgroups: comp.os.msdos.djgpp Subject: Interrupt using assembly, Please help!!! Date: Fri, 31 Jan 1997 12:09:39 -0800 Organization: University of California, Berkeley Lines: 227 Message-ID: NNTP-Posting-Host: haas.berkeley.edu Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Oh, interrupts :( Please help!!!^M ^M The compiler version is 2.01^M ^M My frustration after a week of investigation. I want to use assembly to write^M protected mode interrupt handler using __dpmi_ calls instead of _go32_ calls. ^M I found out __dpmi_set_protected_interrupt_vector() is the same as the _go32_^M except for the second parameter as demonstrated in the first code example.^M ^M The following codes work, as observed by value of counter changing^M command to generate: gcc -o tm1.exe tm1.c t1.s^M --------^M /* tm1.c */^M ^M #include ^M #include ^M #include ^M #include ^M #include ^M ^M _go32_dpmi_seginfo old_handler,my_callback;^M __dpmi_paddr new_seg;^M ^M int counter;^M char *string;^M extern void my_int();^M ^M void init_handler() {^M int error;^M if ((error = _go32_dpmi_get_protected_mode_interrupt_vector(8,^M &old_handler)) == -1) {^M printf ("e1\n");^M exit(1);^M }^M my_callback.pm_offset = (unsigned long)my_int;^M _go32_dpmi_allocate_iret_wrapper(&my_callback);^M new_seg.offset32 = my_callback.pm_offset;^M new_seg.selector = my_callback.pm_selector;^M if ((error = __dpmi_set_protected_mode_interrupt_vector(8,^M &new_seg)) == -1) {^M printf("e2\n");^M exit(1);^M }^M }^M ^M void done_handler() {^M _go32_dpmi_set_protected_mode_interrupt_vector(8,^M &old_handler);^M _go32_dpmi_free_iret_wrapper(&my_callback);^M }^M ^M main() {^M char buffer[80],temp[80];^M int ints;^M ^M counter = 0;^M init_handler();^M ^M ^M printf("Type some text followed by a CR,");^M printf(" or EXIT to quit\n");^M do {^M printf("Counter =%d", counter);^M strcpy(temp, "Hello\n");^M scanf("%s", temp);^M ints = disable(); //clear interrupts^M strcpy(buffer,temp);^M if(ints) enable(); //reenable interrupts^M } while(stricmp(buffer,"EXIT"));^M ^M done_handler();^M }^M ^M ###t1.s^M .global _my_int^M ^M .text^M t_start_of_text:^M _my_int:.global _my_int^M incl _counter^M ret ^M t_end_of_text:^M --------^M ^M Then the frustration started....^M ^M I change tm1.c a bit to use __dpmi calls without the wrapper call, change t1.s^M to use iret instead of ret and put a sti before it. No luck!^M So, I dig into gopint.c to find out what goes on in allocate_wrapper call. ^M I put^M the fill around my assembly code, thinking that was it. Guess what, no luck!^M counter remains 00000000000000....^M After numerous tries with this seemingly small piece of code, I am posting for ^M help! Codes follow:^M ^M command to compile: gcc -o tm2.exe tm2.c t2.s^M /* tm2.c */^M #include ^M #include ^M #include ^M #include ^M #include ^M #include ^M ^M __dpmi_paddr old_handler,my_callback;^M char mystack[1024];^M int stk_bottom = (int) mystack + 1024;^M int counter;^M unsigned short tt_ds;^M char *string;^M extern void my_int();^M ^M void init_handler() {^M int error;^M ^M tt_ds = (unsigned short)_my_ds;^M printf("my_ds:%d, __djgpp_ds_alias: %d\n", _my_ds, __djgpp_ds_alias);^M if ((error = __dpmi_get_protected_mode_interrupt_vector(8,^M &old_handler)) == -1) {^M printf ("e1\n");^M exit(1);^M }^M my_callback.offset32 = (unsigned long) my_int;^M my_callback.selector = (unsigned short)_my_cs;^M if ((error = __dpmi_set_protected_mode_interrupt_vector(8,^M &my_callback)) == -1) {^M printf("e2\n");^M exit(1);^M }^M }^M ^M void done_handler() {^M __dpmi_set_protected_mode_interrupt_vector(8,^M &old_handler);^M }^M ^M main() {^M char buffer[80],temp[80];^M int ints;^M ^M counter = 0;^M init_handler();^M ^M printf("Type some text followed by a CR,");^M printf(" or EXIT to quit\n");^M do {^M printf("Counter =%d", counter);^M strcpy(temp, "Hello\n");^M scanf("%s", temp);^M ints = disable(); //clear interrupts^M strcpy(buffer,temp);^M if(ints) enable(); //reenable interrupts^M } while(stricmp(buffer,"EXIT"));^M ^M done_handler();^M }^M ^M #t2.s^M .global _my_int^M ^M .text^M t_start_of_text:^M _my_int:.global _my_int^M #wrapper code from gopint.c^M #save original registers^M pushw %ds^M pushw %es^M pushw %fs^M pushw %gs^M pushal^M #use current data segment^M mov ___djgpp_ds_alias, %ax^M mov %ax, %ds^M mov %ax, %es^M mov %ax, %fs^M mov %ax, %gs^M #use current stack^M movl $bottom, %ebx^M cld^M #save original esp in ecx^M movl %esp, %ecx^M #save original ss in dx^M mov %ss, %dx^M #use current data segment as ss^M mov %ax, %ss^M #use current stack as esp^M movl %ebx, %esp^M #save original ss and esp^M pushl %edx^M pushl %ecx^M incl _counter^M #restore ss and esp^M popl %eax^M popl %ebx^M mov %bx, %ss^M mov %eax, %esp^M #restore all other registers^M popal^M popw %gs^M popw %fs^M popw %es^M popw %ds^M iret ^M t_end_of_text:^M t_start_of_data: ^M sss: ^M .fill 100, 1, 0^M bottom: ^M .long 0^M t_end_of_data:^M ------^M ^M Please advise to get counter ticking on tm2.c. Many thanks!!!^M ^M Several related questions about the gopint.c comments. ^M 1) Why does it assume only cs and ss is available, thus the stack swapping^M and segment register savings? I thought in flat mode, none of the segments ^M change. ^M 2) Second, there is no sti in the wrapper code, contrary to the FAQ? ^M ^M ^M ^M ^M ^M ^M ^M