This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Calling convention that gets frame pointer register clobbered


 --- Kai Henningsen <kaih@khms.westfalen.de> wrote:
> > unsigned char
> > _EBIOSDISK_getparam (unsigned char disk, ebiosinfo_t *ebiosinfo,
> >                      unsigned char *status)
> >   {
> >   unsigned char carry;
> >
> >   asm (
> > "       int     $0x13           # _EBIOSDISK_getparam   \n"
> > "       mov     %%ah,%1                                 \n"
> > "       setc    %0                                      \n"
> >         : "=qm" (carry), "=qm" (*status), "=S" (*ebiosinfo)
> >         : "a"((unsigned short)0x4800), "d" (disk)
> >         );
> >
> >   return carry;
> >   }

  This BIOS service (interrupt 0x13, service in register %ax 0x4800)
 is initialising the complete structure pointed by ebiosinfo for the
 disk in register %dl - variable "disk".
 The inputs are:
    %ax = 0x4800             (16 bits)
    %dl = disk BIOS number   (8 bits)
    %ds:%si = the address of the buffer to fill-in (16 + 16 bits)
 The outputs are:
    the carry flag set if error
    If carry set the reason of the error in 8 bit register %ah
    If carry clear the structure filled-in (75 bytes)

> >   Using output "=m" (*ebiosinfo) and input "S" (ebiosinfo) is not
> >  completely equivalent because the output part may generate strange
> >  code on some compiler version - but that is the best approximation.
> 
> In any case, that's where your error is. You're claiming to move
> the whole structure when actually you're only trying to move
> the pointer.

 This BIOS service (could be any O.S.) is not moving anything, just
 filling a complete structure of 75 bytes with a meaningfull
 description of the disk. The special thing here is that even if the
 complete structure is an output, its address has to be given somehow
 to int 0x13.

 It is not like if the O.S. service would give the address of a constant
 structure - in this later case the return value would be a pointer.

> Don't lie to the compiler, or the compiler will bite you.

  To get GCC to compile the code, right now you have to lie to it.
  Note what is the lie:
 You say you have one more input, the pointer of your buffer, in
 register %ds:%si
 You say that there is a buffer in memory (not in current stack
 frame - that may be the lie) which will be modified.

  What this code need to correctly compile without lying is that
 instead of writing the output "=m" (*ebiosinfo) you can say
 "=S" (*ebiosinfo).

  What happen is exactly the same as:

typedef struct { char a,b; } s1_t;
typedef struct { long long a,b; } s2_t;

s1_t fct1 (int x) {
  s1_t ret = { x + 1, x - 1};
  return ret;
  }

s2_t fct2 (int x) {
  s2_t ret = { x + 1, x - 1};
  return ret;
  }

  Sorry to not be explicit enought at the first time.
  Etienne.

_________________________________________________________________
Do You Yahoo!? -- Une adresse @yahoo.fr gratuite et en français !
Yahoo! Mail : http://fr.mail.yahoo.com


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