[comp.os.minix] TurboC+1.5.5 protected mode bug

jrw@uncecs.edu (James R. White) (03/25/90)

When using Turbo C to compile 1.5.5, there is a bug when trying to use
protected mode. There are several places where a pointer is converted
to a long with a cast, such as:
    (phys_bytes) some_pointer
(where phys_bytes is typedefed to long)
Now Turbo C has a large model mentality even when compiling for the
tiny model, so it assigns the large model form of the pointer to the
long. So while minix assumes the high order part will be zero, TC sets
it to the value in the segment register. The fix I used was to cast the
pointer to an int, and then to a long. With this fix (and the previously
posted mpx fix) I am now able to boot my TC compiled minix 1.5.5 in
both real and protected mode. Here are the diffs for protect1.c and
protect.c
------------------------------ protect1.c --------------------------
77c77
< 		     data_base + (phys_bytes) rp->p_ldt,
---
> 		     data_base + (phys_bytes)(int) rp->p_ldt,
------------------------------ protect.c ---------------------------
156,159c156,159
< 	data_base + (phys_bytes) gdt;
<   ((struct desctableptr_s *) &gdt[BIOS_IDT_INDEX])->limit = sizeof idt - 1;
<   ((struct desctableptr_s *) &gdt[BIOS_IDT_INDEX])->base =
< 	data_base + (phys_bytes) idt;
---
> 	data_base + (phys_bytes)(int) gdt;
>   ((struct desctableptr_s *) &gdt[BIOS_IDT_INDEX])->limit = sizeof idt - 1;
>   ((struct desctableptr_s *) &gdt[BIOS_IDT_INDEX])->base =
> 	data_base + (phys_bytes)(int) idt;
172c172
<   init_dataseg(&gdt[GDT_INDEX], data_base + (phys_bytes) gdt,
---
>   init_dataseg(&gdt[GDT_INDEX], data_base + (phys_bytes)(int) gdt,
195c195
<   init_dataseg(&gdt[TSS_INDEX], data_base + (phys_bytes) &tss,
---
>   init_dataseg(&gdt[TSS_INDEX], data_base + (phys_bytes)(int) &tss,
202,205c202,205
< 	int_gate(gtp->vec_nr, (phys_bytes) gtp->gate,
< 		 PRESENT | INT_GATE_TYPE | (gtp->privilege << DPL_SHIFT));
<   }
<   int_gate(SYS_VECTOR, (phys_bytes) p_s_call,
---
> 	int_gate(gtp->vec_nr, (phys_bytes)(int) gtp->gate,
> 		 PRESENT | INT_GATE_TYPE | (gtp->privilege << DPL_SHIFT));
>   }
>   int_gate(SYS_VECTOR, (phys_bytes)(int) p_s_call,
224c224
<   int_gate(SYS386_VECTOR, (phys_bytes) s_call,
---
>   int_gate(SYS386_VECTOR, (phys_bytes)(int) s_call,
-----------------------------------------------------------------

jrw@uncecs.edu (James R. White) (03/25/90)

[problem with Turbo C 2.0 compiling 1.5.5 where a pointer would be cast
to a long and TC would put the segment in the upper part.]

Oops. My solution was to cast to an (int) before casting to a (long).
Bruce Evans has pointed out to me that casting to an (unsigned) would
be better because (long)(int) will sign extend while (long)(unsigned)
won't. I got away with (int) because I'm using separate I&D and so
all the pointers being converted were less than 0x8000.