This is the mail archive of the crossgcc@cygnus.com mailing list for the crossgcc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Real mode MS-DOS programs


Is it possible to convince gcc (or djgpp) to produce real mode (as opposed
to protected mode) programs for MS-DOS? Alternatively I would be very
grateful if I could get some guidance on how to correct my problem stated
below.

Regards

Anders Blomdell

------------------------------------------------------------------------------
 Anders Blomdell
 Department of Automatic Control        Email: anders.blomdell@control.lth.se
 Lund Institute of Technology           Phone: +46 46 222 4625
 Box 118, S-221 00 Lund, Sweden         Fax:   +46 46 138118




If you are not interested in MS-DOS segmentation issues, please stop
reading here.

Scenario:

In order to automagically configure all our Intel machines with Windows NT,
I need a program that finds out which ethernet adapter a certain machine is
equipped with. In order to do that, I borrowed some of the PCI-BIOS code
from the Linux system, which worked fine on our older Pentium systems, but
fails miserably on the latest batch of computers (Phoenix BIOS 4.0 Release
6.0).

The problem is that the following call (to 0xfd9df)

    __asm__("lcall (%%edi)\n\t"
            "jc 1f\n\t"
            "xor %%ah, %%ah\n"
            "1:\tshl $8, %%eax\n\t"
            "movw %%bx, %%ax"
            : "=d" (signature),
              "=a" (pack)
            : "1" (PCIBIOS_PCI_BIOS_PRESENT),
              "D" (&pci_indirect)
            : "bx", "cx");


leads to the following segmentation fault

  Exiting due to signal SIGSEGV
  General Protection Fault at eip=000fda02
  eax=00000004 ebx=0004f080 ecx=00000000 edx=000000d7 esi=000fd9a3 edi=00009ca0
  ebp=0004d424 esp=0004d420 program=E:\MSDOS\DETECT.EXE
  cs: sel=00cf  base=00000000  limit=000fffff
  ds: sel=00af  base=10000000  limit=0005ffff
  es: sel=00af  base=10000000  limit=0005ffff
  fs: sel=0087  base=0002e150  limit=0000ffff
  gs: sel=00bf  base=00000000  limit=ffffffff
  ss: sel=00af  base=10000000  limit=0005ffff


after executing approximately 20 instructions of the BIOS code below:

   fd9df:       60              pusha
   fd9e0:       8b ec           movl   %esp,%ebp
   fd9e2:       f9              stc
   fd9e3:       9c              pushf
   fd9e4:       c6 45 1d 81     movb   $0x81,0x1d(%ebp)
   fd9e8:       3c 0f           cmpb   $0xf,%al
   fd9ea:       77 29           ja     fda15 <_x+fd9c9>
   fd9ec:       8d 35 bf 01 00  leal   0x1bf,%esi
   fd9f1:       00
   fd9f2:       e8 9e 03 00 00  call   fdd95 <_x+fdd49>
   fd9f7:       25 ff 00 00 00  andl   $0xff,%eax
   fd9fc:       66 c1 e0 02     shlw   $0x2,%ax
   fda00:       03 f0           addl   %eax,%esi	# Error occurs here
   fda02:       8b 36           movl   (%esi),%esi
   fda04:       e8 8c 03 00 00  call   fdd95 <_x+fdd49>
   fda09:       ff d6           call   *%esi
   fda0b:       72 08           jb     fda15 <_x+fd9c9>
   fda0d:       c6 45 1d 00     movb   $0x0,0x1d(%ebp)
        ...
   fdd95:       e8 01 00 00 00  call   fdd9b <_x+fdd4f>
   fdd9a:       c3              ret
   fdd9b:       03 34 24        addl   (%esp,1),%esi
   fdd9e:       81 ee ba 05 00  subl   $0x5ba,%esi
   fdda3:       00
   fdda4:       c3              ret

My guess (I'm not very good at the Intel segmented architecture) is that
some of the segment descriptors should be modified prior to the call, but
the only results I have achieved so far, is to move the segmentation fault
to the call itself...