This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Calling convention that gets frame pointer register clobbered
- From: Etienne Lorrain <etienne_lorrain at yahoo dot fr>
- To: Kai Henningsen <kaih at khms dot westfalen dot de>
- Cc: gcc at gcc dot gnu dot org
- Date: Mon, 22 Dec 2003 14:36:31 +0100 (CET)
- Subject: 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