By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,203 Members | 1,549 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,203 IT Pros & Developers. It's quick & easy.

procedure parameter struct order

P: n/a
Hi, there

while mixing assembler and c code I got the following question:

struct bar {
int bar_val1;
int bar_val2;
(...)
}

void foo(struct bar)
{
DO_SOMETHING;
};
My question is, if the order of the struct vars on the stack (eg.
bar_val1, bar_val2)is defined within C.

In assembler code the values should be pushed onto the stack and then
foo should be called. My code is 'working for me', but I want to know,if
it is a defined behaviour, or it is gcc specific.

thx in advance

yoon

Nov 14 '05 #1
Share this Question
Share on Google+
19 Replies


P: n/a
"Yoon Soo" <y0*****@gmx.net> wrote in message
news:c1*************@ID-98218.news.uni-berlin.de...
Hi, there

while mixing assembler and c code I got the following question:

struct bar {
int bar_val1;
int bar_val2;
(...)
}

void foo(struct bar)
{
DO_SOMETHING;
};
My question is, if the order of the struct vars on the stack (eg.
bar_val1, bar_val2)is defined within C.


No. The standards do not even specify that a stack is used for argument
passing at all (and indeed, it sometimes isn't). The "calling convention" is
implementation specific.
Nov 14 '05 #2

P: n/a
Yoon Soo <y0*****@gmx.net> wrote:
while mixing assembler and c code I got the following question:

struct bar {
int bar_val1;
int bar_val2;
(...)
}

void foo(struct bar)
{
DO_SOMETHING;
};
My question is, if the order of the struct vars on the stack (eg.
bar_val1, bar_val2)is defined within C.


It is not even defined whether they are on a stack to begin with; small
structs could be passed in a couple of registers, for example.
Mixing assembly and C is deep into implementation-dependent territory
anyway, so if I were you I'd ask in a newsgroup that discusses the
specifics of your compiler; if you're tying your code into a single
compiler version anyway by including assembly, it's not going to hurt to
tie it a bit further by depending on its order. But do document that
you've done this.

Richard
Nov 14 '05 #3

P: n/a
Richard Bos wrote:
My question is, if the order of the struct vars on the stack (eg.
bar_val1, bar_val2)is defined within C.

It is not even defined whether they are on a stack to begin with; small
structs could be passed in a couple of registers, for example.


I forgot to mention, that foo is declared with the attribute regparm(0)
... which is (afaik) also depending on the implementation of the
compiler, so the stack should be used in any cases.
Mixing assembly and C is deep into implementation-dependent territory
anyway, so if I were you I'd ask in a newsgroup that discusses the
specifics of your compiler; if you're tying your code into a single
compiler version anyway by including assembly, it's not going to hurt to
tie it a bit further by depending on its order. But do document that
you've done this.


thx for the replies. I think I will include some inline asm codes into
foo to be sure, that the correct parameters are found on the stack.

yoon

Nov 14 '05 #4

P: n/a
>>My question is, if the order of the struct vars on the stack (eg.
bar_val1, bar_val2)is defined within C.

No. The standards do not even specify that a stack is used for argument
passing at all (and indeed, it sometimes isn't). The "calling convention" is
implementation specific.


That's right, but he didn't use the right vocabulary, and you overlooked
(in my opinion) the point he was trying to figure out.

He was asking whether the MEMBERS of a given struct would always have
the same order (ie. offsets), whether the struct is passed as an
argument of a function, or used as a variable (or whatever), and the
short answer is: YES. I think the norm actually guarantees that the
members of a struct are always in the same order as they are declared.
Nov 14 '05 #5

P: n/a
Guillaume <gr*******@NO-SPAMmail.com> wrote:
My question is, if the order of the struct vars on the stack (eg.
bar_val1, bar_val2)is defined within C.


No. The standards do not even specify that a stack is used for argument
passing at all (and indeed, it sometimes isn't). The "calling convention" is
implementation specific.


That's right, but he didn't use the right vocabulary, and you overlooked
(in my opinion) the point he was trying to figure out.

He was asking whether the MEMBERS of a given struct would always have
the same order (ie. offsets), whether the struct is passed as an
argument of a function, or used as a variable (or whatever), and the
short answer is: YES.


Short, but misleading. The answer is "yes, when accessed using a C
pointer"; but this doesn't tell you anything about what the assembly
code sees.
For example, if you do not use the & operator inside the function, it
might be more efficient to pass the struct in registers instead of on
the stack, if it's small; the C code cannot tell the difference, if it
doesn't ask for the struct's address. But for the assembly code, it
would be another kettle of fish entirely.

Richard
Nov 14 '05 #6

P: n/a
"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:40****************@news.individual.net...
Guillaume <gr*******@NO-SPAMmail.com> wrote:
>My question is, if the order of the struct vars on the stack (eg.
>bar_val1, bar_val2)is defined within C.

No. The standards do not even specify that a stack is used for argument
passing at all (and indeed, it sometimes isn't). The "calling convention" is implementation specific.


That's right, but he didn't use the right vocabulary, and you overlooked
(in my opinion) the point he was trying to figure out.

He was asking whether the MEMBERS of a given struct would always have
the same order (ie. offsets), whether the struct is passed as an
argument of a function, or used as a variable (or whatever), and the
short answer is: YES.


Short, but misleading. The answer is "yes, when accessed using a C
pointer"; but this doesn't tell you anything about what the assembly
code sees.
For example, if you do not use the & operator inside the function, it
might be more efficient to pass the struct in registers instead of on
the stack, if it's small; the C code cannot tell the difference, if it
doesn't ask for the struct's address. But for the assembly code, it
would be another kettle of fish entirely.

Richard


Which is yet another reason why I prefer to
use a struct pointer, rather than a copy of
the struct (whether passing into or out of
a function call). By using a struct pointer,
the OP's "problem" is reduced to finding
the pointer that was passed to the assembler
function, rather than where each member is
located on the stackframe (if there *is* a
stackframe).

After finding the pointer, he knows that the
struct members will be in ascending order, but
be sure to account for inter-member gaps for
alignment (also implementation dependent).
--
----------------------------
Jeffrey D. Smith
Farsight Systems Corporation
24 BURLINGTON DRIVE
LONGMONT, CO 80501-6906
http://www.farsight-systems.com
z/Debug debugs your Systems/C programs running on IBM z/OS!
Are ISV upgrade fees too high? Check our custom product development!
Nov 14 '05 #7

P: n/a
Roc
> >
My question is, if the order of the struct vars on the stack (eg.
bar_val1, bar_val2)is defined within C.
No. The standards do not even specify that a stack is used for argument
passing at all (and indeed, it sometimes isn't). The "calling convention"

is implementation specific.


Then is the keyword "pascal" implementation specific?

I thought I read was it introduced to influence/enforce argument
stack-order... but that was a long time ago...
Nov 14 '05 #8

P: n/a
Roc wrote:
My question is, if the order of the struct vars on the stack (eg.
bar_val1, bar_val2)is defined within C.


No. The standards do not even specify that a stack is used for argument
passing at all (and indeed, it sometimes isn't). The "calling convention"


is
implementation specific.

Then is the keyword "pascal" implementation specific?

I thought I read was it introduced to influence/enforce argument
stack-order... but that was a long time ago...


Yes, the identifier "pascal" is implementation specific.
Some compilers use it to specify how the parameters are
passed to a receiving function.

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book

Nov 14 '05 #9

P: n/a
In article <10*************@corp.supernews.com>,
"Roc" <no****@aqssys.com> wrote:

My question is, if the order of the struct vars on the stack (eg.
bar_val1, bar_val2)is defined within C.


No. The standards do not even specify that a stack is used for argument
passing at all (and indeed, it sometimes isn't). The "calling convention"

is
implementation specific.


Then is the keyword "pascal" implementation specific?


Umm, yes. The word "pascal" doesn't appear anywhere in the standard.

Nov 14 '05 #10

P: n/a
"Guillaume" <gr*******@NO-SPAMmail.com> wrote in message
news:40**********************@news.club-internet.fr...
My question is, if the order of the struct vars on the stack (eg.
bar_val1, bar_val2)is defined within C.
No. The standards do not even specify that a stack is used for
argument passing at all (and indeed, it sometimes isn't). The
"calling convention" is implementation specific.


That's right, but he didn't use the right vocabulary, and you
overlooked (in my opinion) the point he was trying to figure out.


Perhaps...
He was asking whether the MEMBERS of a given struct would always
have the same order (ie. offsets) [...]


I read that the OP was asking whether the standard specified how to retrieve
(in assembler) the values from a struct passed as a function argument. This
falls at the first hurdle: the calling convention is implementation defined.

It would also fall at the second hurdle: while the order of members /is/ -
as you said - defined by the standard, member offsets are not, due to
implementation-defined padding. But does this matter, if you never get
beyond the first hurdle?

Alex
Nov 14 '05 #11

P: n/a
Guillaume wrote:
That's right, but he didn't use the right vocabulary, and you overlooked
(in my opinion) the point he was trying to figure out.

He was asking whether the MEMBERS of a given struct would always have
the same order (ie. offsets), whether the struct is passed as an
argument of a function, or used as a variable (or whatever), and the
short answer is: YES. I think the norm actually guarantees that the
members of a struct are always in the same order as they are declared.


yes, I think I really used the wrong vocabulary.

My question was exactly: if a struct is passed as an argument of a
function, the members of this struct would always have the same order on
the stack..or to be more exact, if the function expects to find the
members in the order they are declared. Within only c this is not that
great problem, but since I am pushing the values manually onto the
stack, I need to know, where the translated c code will expect them
conform to the c standard.

And if this is guaranted by the norm.

To explain my thoughts: Maybe a compiler xyz could say, that it is
better to reorder the struct for better performance or similar. So I
will push the first member and the function is expecting the second one
there instead.

thx for your short answer. I will try to find something about it in the
norm.

yoon

Nov 14 '05 #12

P: n/a
[original poster wrote]
My question is, if the order of the struct vars on the stack (eg.
bar_val1, bar_val2)is defined within C.
Richard Bos wrote:
It is not even defined whether they are on a stack to begin with; small
structs could be passed in a couple of registers, for example.

In article <news:c1*************@ID-98218.news.uni-berlin.de>
Yoon Soo <y0*****@gmx.net> writes:I forgot to mention, that foo is declared with the attribute regparm(0)
.. which is (afaik) also depending on the implementation of the
compiler, so the stack should be used in any cases.


Indeed, it does depend on the compiler -- but be aware that just
because you force the compiler to pass the structure on its
implementation-specific stack does *not* mean that the structure
will be where you expect it to be.

In particular, I once fixed some (seriously scary) i386-specific
boot code that included, in part:

void f(struct S arg) {
... make changes to arg.fields ...
now call other functions, or even just return
}

plus assembly-language code that carefully called f() with a known
stack pointer and secret arrangements to access the changed values
in arg.fields in those other functions or after f() returned.

This actually worked in versions 1.x and 2.x of the compiler, but
gcc3 would sometimes choose to *copy* the argument "arg" to local
storage before making changes to arg.fields, so that the changes
were no longer being made to the special, known-stack-position
struct. Debugging this was "interesting" because the code would
hang very early in the boot process, long before there was any way
to debug it without an ICE, and making *any* change to the code --
including even a single "write a byte to the display memory to
observe progress" -- changed gcc's internal decisions as to whether
and when to copy the argument. (Thus, this was what is often called
a "Heisenbug", whose behavior changes when you attempt to observe
it.)

The fix for this was simple enough and brings us back on topic. I
changed f() to read:

void f(struct S *arg) {
... make changes to arg->fields ...
now call other functions, or return
}

This did take a whole extra four bytes of stack space, along with
an extra instruction or two in the assembly startup; but why whoever
it was who wrote the original might have been concerned about this
is beyond me since f() not only had its own compiler-generated
(hence unpredictable) stack usage but also called other functions
which were not *that* tightly code-and-stack-space-constrained.

The moral, as it were, is also on-topic: even if you know all about
your compiler, choosing to depend on it may be a mistake, as a
future version of that compiler may change its internals. If there
is a way to write the code so that it *has* to work according to
the language rules, consider using that code instead.

Finally, one last note: The offsets of the various fields of a
structure can be obtained with the offsetof() macro, and will be
in ascending order according to the structure's definition. There
may be gaps for "struct padding" between fields, but the first
field will be at offset 0, the next at an offset no less than
"sizeof" the first field, the next no less than "sizeof" that field
further on, and so on.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #13

P: n/a
On Mon, 23 Feb 2004 13:35:37 +0100, Yoon Soo <y0*****@gmx.net> wrote
in comp.lang.c:
Richard Bos wrote:
My question is, if the order of the struct vars on the stack (eg.
bar_val1, bar_val2)is defined within C.

It is not even defined whether they are on a stack to begin with; small
structs could be passed in a couple of registers, for example.


I forgot to mention, that foo is declared with the attribute regparm(0)


There is no such thing as "attribute regparm(0)" in C. You are
talking about some non-standard extension provided by your particular
compiler. It is both nonsense and off-topic here, and needs to be
asked in a support group for your compiler.
.. which is (afaik) also depending on the implementation of the
compiler, so the stack should be used in any cases.
No, it is not something that C defines as "implementation-defined", it
is something that is not C at all.
Mixing assembly and C is deep into implementation-dependent territory
anyway, so if I were you I'd ask in a newsgroup that discusses the
specifics of your compiler; if you're tying your code into a single
compiler version anyway by including assembly, it's not going to hurt to
tie it a bit further by depending on its order. But do document that
you've done this.


thx for the replies. I think I will include some inline asm codes into
foo to be sure, that the correct parameters are found on the stack.


Likewise, there is no such thing as inline assembly language code in
the C language. All such features are again non-standard and specific
to your compiler.
yoon


There is nothing wrong with using non-standard extensions, you just
need to realize that they are not discussed here because they are not
part of the language, and discuss them in groups for the specific
compiler that provides them.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #14

P: n/a
On Mon, 23 Feb 2004 14:52:43 +0100, Guillaume
<gr*******@NO-SPAMmail.com> wrote in comp.lang.c:
My question is, if the order of the struct vars on the stack (eg.
bar_val1, bar_val2)is defined within C.

No. The standards do not even specify that a stack is used for argument
passing at all (and indeed, it sometimes isn't). The "calling convention" is
implementation specific.


That's right, but he didn't use the right vocabulary, and you overlooked
(in my opinion) the point he was trying to figure out.

He was asking whether the MEMBERS of a given struct would always have
the same order (ie. offsets), whether the struct is passed as an
argument of a function, or used as a variable (or whatever), and the
short answer is: YES. I think the norm actually guarantees that the
members of a struct are always in the same order as they are declared.


The short answer is: NO WAY TO TELL.

On most of the platforms I use today, the struct would no be passed on
"the stack" at all, but in two registers.

The passed copy would never reside in memory at all in many cases. If
an address of the copy were needed, for example if the function
receiving the copy in turn called another function and passed a
pointer to the passed structure copy, the called function would
provide some space in memory and copy the register contents to the
appropriate addresses. The caller, passing a copy, would neither know
nor care that this might eventually take place.

C does not specify anything about "the stack" or about anything passed
by value. And the as-if rule certainly allows the compiler to hold
any object entirely in registers or other non-memory locations so long
as its address is not taken.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #15

P: n/a
Yoon Soo <y0*****@gmx.net> wrote:
My question was exactly: if a struct is passed as an argument of a
function, the members of this struct would always have the same order on
the stack..or to be more exact, if the function expects to find the
members in the order they are declared.


No. In particular, as has already been written by several people, you do
not even know whether the arguments are passed on the stack in the first
place. All you know is that to code using C pointers, it must appear as
all members are at the same place in memory. Even this might mean that
the struct is copied into some (cheap, fast, plentiful) allocated
memory, and a hidden pointer to this copied struct is passed on the
(slow, small) stack.
But even when the stack is used, you do not know that the whole stack is
passed, or in what order. For example, take this code:

struct rectangle {
char *label;
int width;
int heigth;
t_colour background;
t_colour foreground;
t_pattern hatching;
int top;
int left;
}

int rect_size(struct rectangle r)
{
if (r.hatching==PAT_BLANK)
return 0;
return r.width*r.heigth;
}

Since nothing in the function references anything else in the structure,
and there is no possible way for you to detect the difference, the
compiler would be quite correct if, behind the scenes, all it pushed on
the stack were the hatching, width and heigth members, and adjusted the
object code for the function accordingly. The program would function
identically, except that it spends a few cycles less pushing and popping
needless struct members. No problem, in ISO C.
Now along comes someone who shoves a bit of assembly code inside that
function which starts manipulating the SP register as if all the members
are right there on the stack. Oops...

Richard
Nov 14 '05 #16

P: n/a
Jack Klein wrote:
There is nothing wrong with using non-standard extensions, you just
need to realize that they are not discussed here because they are not
part of the language, and discuss them in groups for the specific
compiler that provides them.


in some points you are right, but you did not got the key point. Neither
my questions nor the informations I got from this thread was related to
the non-standard extensions.

My key question was related to the standard..of course I could ask that
to people who does not care much about ISO and similar but I doubt I
would get there the informations I got here..and there were many helpful
informations.

however, greets

yoon

Nov 14 '05 #17

P: n/a
Richard Bos wrote:

Since nothing in the function references anything else in the structure,
and there is no possible way for you to detect the difference, the
compiler would be quite correct if, behind the scenes, all it pushed on
the stack were the hatching, width and heigth members, and adjusted the
object code for the function accordingly. The program would function
identically, except that it spends a few cycles less pushing and popping
needless struct members. No problem, in ISO C.

^^^^^^^^^^^^^^^^^^^^^^^^
that's the (main) info I wanted. Many thanks for your clear example and
the explanations to it.

yoon

Nov 14 '05 #18

P: n/a
On Tue, 24 Feb 2004 10:06:07 GMT, rl*@hoekstra-uitgeverij.nl (Richard
Bos) wrote:
Yoon Soo <y0*****@gmx.net> wrote:
My question was exactly: if a struct is passed as an argument of a
function, the members of this struct would always have the same order on
the stack..or to be more exact, if the function expects to find the
members in the order they are declared.
No. In particular, as has already been written by several people, you do
not even know whether the arguments are passed on the stack in the first


True. Or if there even is a (single) stack as such, although to allow
functions to be recursive, which *is* required, there must be some way
to make automatic (aka local) variables operate stackishly.
place. All you know is that to code using C pointers, it must appear as
all members are at the same place in memory. Even this might mean that
Not quite the same place, that would be a union. In a contiguous chunk
of memory than can be memcpy'ed to another struct object of the same
type and work, yes; and with member addresses/offsets in ascending
order, but as noted elsethread possibly skipping padding.
the struct is copied into some (cheap, fast, plentiful) allocated
memory, and a hidden pointer to this copied struct is passed on the
(slow, small) stack.
Stacks are rarely slow and small, usually they are fast -- often
distinctly faster than general memory, because of better cache
locality -- but may be small(ish). Or, often a pointer (but not a full
struct) can be passed in register(s), which are usually (very) small
and (very) fast.
But even when the stack is used, you do not know that the whole stack is
passed, or in what order. For example, take this code:

struct rectangle { [snipped]
}
(Nit: missing semicolon)
int rect_size(struct rectangle r)
{
if (r.hatching==PAT_BLANK)
return 0;
return r.width*r.heigth;
}

Since nothing in the function references anything else in the structure,
and there is no possible way for you to detect the difference, the
compiler would be quite correct if, behind the scenes, all it pushed on
the stack were the hatching, width and heigth members, and adjusted the
object code for the function accordingly. The program would function
identically, except that it spends a few cycles less pushing and popping
needless struct members. No problem, in ISO C.


Although this function could be called from a separately compiled
"module" (strictly, translation unit), and the compiler, or linker, or
something, would have to make sure that such calls also do that same
optimization, which on many/most? systems is so hard as to be
practically impossible. Now if you made the function 'static', it
would be somewhat more likely. In fact, if the definition is visible
during compilation -- as it must be, if static -- there's a fair
chance it will be inlined, and nothing will be pushed at all. Perhaps
even a slightly better chance in C99 if you *specify* 'inline'.

(PS- it's spelled 'height', or spelt depending on your location.)

- David.Thompson1 at worldnet.att.net
Nov 14 '05 #19

P: n/a
Dave Thompson <da*************@worldnet.att.net> wrote:
On Tue, 24 Feb 2004 10:06:07 GMT, rl*@hoekstra-uitgeverij.nl (Richard
Bos) wrote:
the struct is copied into some (cheap, fast, plentiful) allocated
memory, and a hidden pointer to this copied struct is passed on the
(slow, small) stack.
Stacks are rarely slow and small, usually they are fast -- often
distinctly faster than general memory, because of better cache
locality -- but may be small(ish).


Usually, but hey, we're talking about guarantees here. The above _could_
happen.
Since nothing in the function references anything else in the structure,
and there is no possible way for you to detect the difference, the
compiler would be quite correct if, behind the scenes, all it pushed on
the stack were the hatching, width and heigth members, and adjusted the
object code for the function accordingly. The program would function
identically, except that it spends a few cycles less pushing and popping
needless struct members. No problem, in ISO C.


Although this function could be called from a separately compiled
"module" (strictly, translation unit), and the compiler, or linker, or
something, would have to make sure that such calls also do that same
optimization, which on many/most? systems is so hard as to be
practically impossible.


Again, I know, but it's not impossible. It might even be worth the
trouble.
(PS- it's spelled 'height', or spelt depending on your location.)


Damn, I was wondering whether I'd spelled that correctly!

Richard
Nov 14 '05 #20

This discussion thread is closed

Replies have been disabled for this discussion.