Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Re: x86 Stack Confusion

Reply
Thread Tools

Re: x86 Stack Confusion

 
 
Chuck F.
Guest
Posts: n/a
 
      01-09-2006
Dag-Erling Smørgrav wrote:
> "osmium" <> writes:
>
>> When a knowledgeable person says "C calling convention",
>> *this* is what he means. There is nothing analogous to
>> printf() with it's indeterminate number of parameters in,
>> Pascal, for example.

>
> Yes, there is. Write() and WriteLn() both take a variable
> number of arguments. There is however no way for the programmer
> to define a procedure which takes a variable number of
> arguments.


<OT>
No there isn't. writeln(f) is the actual function. If the source
code reads "writeln(f, x, y)" it is expanded, in the compiler, to
"write(f, x); write(f, y); writeln(f)". A similar process applies
to write(f, x, y) which expands to "write(f, x); write(f, y)". The
same process applies to read and readln. If the first parameter
does not specify a file then output (or input) is assumed.

Since the expansion is done before code generation, there is no
need for a variadic function mechanism, and all parameter types can
be properly checked.

Another point is that the individual write (or read) calls operate
on a single item, of known type. The compiler calls the
appropriate i/o routine for the type, so a linkage is likely to
show such things as writeint, writereal, writestring, etc. This
totally avoids the expense of loading a monster interpreter to
process format strings.

Don't argue with me on this; I have been using and implementing
Pascal for nearly 30 years. If you want more details see the
Pascal standards (ISO7185 and ISO10206) or use email.
</OT>

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      01-09-2006
"Chuck F. " <> writes:
> Grumble wrote:
>> As far as I understand, C89 and C99 leave the details of
>> parameter passing up to the implementation. For that reason,
>> I've claimed in comp.lang.asm.x86 that there is no such thing as
>> "the C calling convention". Am I mistaken? ]

>
> No. However, C is almost unique among languages in having the error
> prone variadic functions available, which in turn mandate having the
> first parameter in a known place, and makes the reverse order
> (assuming a stack, which is not necessary) attractive.


Not just the first parameter; there can be one or more parameters
before the "...".

Before C89's introduction of prototypes, an particularly the "..."
syntax, there was generally no way for a compiler to tell whether
some_func(a, b, c, d);
was an ordinary function call or a call to a function expecting a
variable number and type of arguments. The compiler had to generate
the same kind of call for either case, and the function had to use
some technique that knew where to find the parameter values (typically
using the old <varargs.h> header, but there were uglier techniques
before that was introduced).

With modern prototypes, compilers are free to use a different and more
efficient calling convention for ordinary functions than for functions
that take a variable number of arguments (since a call to the latter
without a prototype invokes undefined behavior) -- but as far as I
know, most compilers have kept the old calling conventions. So, for
example, printf("%s\n", "Hello, world") is likely to work correctly
even if no prototype is visible, because the calling convention was
designed before prototypes existed.

This is, of course, no excuse the required "#include <stdio.h>".

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      01-09-2006
(Dag-Erling Smørgrav) writes:
> "osmium" <> writes:
>> When a knowledgeable person says "C calling convention", *this* is
>> what he means. There is nothing analogous to printf() with it's
>> indeterminate number of parameters in, Pascal, for example.

>
> Yes, there is. Write() and WriteLn() both take a variable number of
> arguments. There is however no way for the programmer to define a
> procedure which takes a variable number of arguments.


Yes, but as I recall the Write and WriteLn procedures, unlike C's
printf(), are "magical". There's no format string, so it's up to the
compiler to generate code based on the actual argument types. A
compiler might typically generate a distinct procedure call for each
argument. It's more like special-case overloading than C's "..."
mechanism. Since the compiler can do whatever it likes, there's no
need for special-purpose calling conventions to make everything come
out right.

This is perhaps marginally off-topic, but it does illustrate some of
the design decisions that went into C. C implements its I/O functions
using (more or less) ordinary function calls, while Pascal uses
compiler magic.

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
John Devereux
Guest
Posts: n/a
 
      01-09-2006
Keith Thompson <kst-> writes:

> (Dag-Erling Smørgrav) writes:
>> "osmium" <> writes:
>>> When a knowledgeable person says "C calling convention", *this* is
>>> what he means. There is nothing analogous to printf() with it's
>>> indeterminate number of parameters in, Pascal, for example.

>>
>> Yes, there is. Write() and WriteLn() both take a variable number of
>> arguments. There is however no way for the programmer to define a
>> procedure which takes a variable number of arguments.

>
> Yes, but as I recall the Write and WriteLn procedures, unlike C's
> printf(), are "magical". There's no format string, so it's up to the
> compiler to generate code based on the actual argument types. A
> compiler might typically generate a distinct procedure call for each
> argument. It's more like special-case overloading than C's "..."
> mechanism. Since the compiler can do whatever it likes, there's no
> need for special-purpose calling conventions to make everything come
> out right.
>
> This is perhaps marginally off-topic, but it does illustrate some of
> the design decisions that went into C. C implements its I/O functions
> using (more or less) ordinary function calls, while Pascal uses
> compiler magic.


Actually gcc for example will typically silently replace

printf("Hello\n");

with

puts("Hello\n");


This makes hello.c 3k long on my system. The compiler does interpret
the format string, and uses the full printf where needed. This also
allows it to catch errors where the parameters do not match the format
string.


--

John Devereux
 
Reply With Quote
 
jacob navia
Guest
Posts: n/a
 
      01-09-2006
Keith Thompson a écrit :
> jacob navia <> writes:
> [snip]
>
>>There is no C calling convention. The "C" calling convention is defined
>>by the compiler that compiles the operating system, usually written
>>in C.
>>
>>Under the linux OS, the gcc compiler defines the calling convention
>>rules, and other compilers must obey whatever gcc decides is the
>>calling convention. If not, they would be faced with the
>>herculean task of rewriting the whole OS.
>>
>>Under the windows OS, the compiler that compiled the OS is MSVC,
>>and other compilers must follow the conventions of that compiler.
>>
>>In newer systems, like the new x64 systems, there is no "right to left",
>>nor "left to right" since four or more arguments are passed in
>>the register file.
>>
>>For instance, you can pass up to 4 arguments to a function directly
>>in registers under windows 64 bits. Linux 64 bits is even more ambitious
>>and much more parameters are passed in registers using both the
>>integer and the floating point register file. (for x86 systems)
>>
>>In general, in each system there is something like an "ABI" (Application
>>Binary Interface) that defines what the conventions of the OS are. Since
>>C is a language that interfaces directly to the OS, calling conventions
>>are highly OS specific.
>>
>>Most compilers give the user the possibility of choosing the calling
>>convention for either all the functions or for specific functions
>>using markers in the declaration header of each function. For instance:
>>
>>int _stdcall fn(int a,int b) { /* ... */ }
>>
>>In most compilers the "cdecl" marker is the default, i.e. the ABI
>>defined calling convention. Note that the standard never defines
>>"cdecl".

>
>
> All of this is x86-specific.
>
> I have no idea whether "most compilers" have things called "_stdcall"
> or "cdecl", but I've never used either.
>


If you re-read what I said, you will notice that I never said that
"most compilers have things called _stdcall", but that they have
"markers" to indicate the preferred calling convention. The _stdcall
was just an example of a marker. Gcc uses other markers, and Borland
yet another. There are compilers (definitely) with only ONE calling
convention but most of them do have several, and they do use some
syntax to allow the user to specify which one he/she prefers.

The _stdcall calling convention is called "pascal" in some compilers,
and means that insetad of the caller adjusting the stack after a call,
it is the callee that does it. This is more efficient and can save
approximately 5% of code size, depending on the machine.

jacob
 
Reply With Quote
 
Mark B
Guest
Posts: n/a
 
      01-09-2006
"John Devereux" <> wrote in message
news:...

<snip>
> Actually gcc for example will typically silently replace
>
> printf("Hello\n");
>
> with
>
> puts("Hello\n");


Doubtful... those 2 lines are not equivalent.




 
Reply With Quote
 
Robert Gamble
Guest
Posts: n/a
 
      01-09-2006
John Devereux wrote:
> Keith Thompson <kst-> writes:
>
> > (Dag-Erling Smørgrav) writes:
> >> "osmium" <> writes:
> >>> When a knowledgeable person says "C calling convention", *this* is
> >>> what he means. There is nothing analogous to printf() with it's
> >>> indeterminate number of parameters in, Pascal, for example.
> >>
> >> Yes, there is. Write() and WriteLn() both take a variable number of
> >> arguments. There is however no way for the programmer to define a
> >> procedure which takes a variable number of arguments.

> >
> > Yes, but as I recall the Write and WriteLn procedures, unlike C's
> > printf(), are "magical". There's no format string, so it's up to the
> > compiler to generate code based on the actual argument types. A
> > compiler might typically generate a distinct procedure call for each
> > argument. It's more like special-case overloading than C's "..."
> > mechanism. Since the compiler can do whatever it likes, there's no
> > need for special-purpose calling conventions to make everything come
> > out right.
> >
> > This is perhaps marginally off-topic, but it does illustrate some of
> > the design decisions that went into C. C implements its I/O functions
> > using (more or less) ordinary function calls, while Pascal uses
> > compiler magic.

>
> Actually gcc for example will typically silently replace
>
> printf("Hello\n");
>
> with
>
> puts("Hello\n");


ITYM:
puts("Hello");

Robert Gamble

 
Reply With Quote
 
jacob navia
Guest
Posts: n/a
 
      01-09-2006
John Devereux a écrit :
>
> Actually gcc for example will typically silently replace
>
> printf("Hello\n");
>
> with
>
> puts("Hello\n");
>
>
> This makes hello.c 3k long on my system. The compiler does interpret
> the format string, and uses the full printf where needed. This also
> allows it to catch errors where the parameters do not match the format
> string.
>
>


Replacing printf with puts can be only done when the return value
is not used, since puts returns "some nonnegative value" according to
the standard, not the number of characters written.
 
Reply With Quote
 
Flash Gordon
Guest
Posts: n/a
 
      01-09-2006
jacob navia wrote:
> John Devereux a écrit :
>>
>> Actually gcc for example will typically silently replace
>> printf("Hello\n");
>>
>> with
>>
>> puts("Hello\n");
>>
>> This makes hello.c 3k long on my system. The compiler does interpret
>> the format string, and uses the full printf where needed. This also
>> allows it to catch errors where the parameters do not match the format
>> string.

>
> Replacing printf with puts can be only done when the return value
> is not used, since puts returns "some nonnegative value" according to
> the standard, not the number of characters written.


If the implementation wants to do that replacement, it can make puts
return the number of characters written, since in this universe the
number of characters written will always be non-negative. I assume that
gcc only makes this replacement on systems where it knows that this is
the non-negative value that will be returned.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
 
Reply With Quote
 
John Devereux
Guest
Posts: n/a
 
      01-09-2006
"Robert Gamble" <> writes:

> John Devereux wrote:
>> Keith Thompson <kst-> writes:
>>
>> > (Dag-Erling Smørgrav) writes:
>> >> "osmium" <> writes:
>> >>> When a knowledgeable person says "C calling convention", *this* is
>> >>> what he means. There is nothing analogous to printf() with it's
>> >>> indeterminate number of parameters in, Pascal, for example.
>> >>
>> >> Yes, there is. Write() and WriteLn() both take a variable number of
>> >> arguments. There is however no way for the programmer to define a
>> >> procedure which takes a variable number of arguments.
>> >
>> > Yes, but as I recall the Write and WriteLn procedures, unlike C's
>> > printf(), are "magical". There's no format string, so it's up to the
>> > compiler to generate code based on the actual argument types. A
>> > compiler might typically generate a distinct procedure call for each
>> > argument. It's more like special-case overloading than C's "..."
>> > mechanism. Since the compiler can do whatever it likes, there's no
>> > need for special-purpose calling conventions to make everything come
>> > out right.
>> >
>> > This is perhaps marginally off-topic, but it does illustrate some of
>> > the design decisions that went into C. C implements its I/O functions
>> > using (more or less) ordinary function calls, while Pascal uses
>> > compiler magic.

>>
>> Actually gcc for example will typically silently replace
>>
>> printf("Hello\n");
>>
>> with
>>
>> puts("Hello\n");

>
> ITYM:
> puts("Hello");



Yes, you are correct! - I admit I never knew that puts() appends a
newline... In fact the only reason I ever encountered it in the first
place is tracking down why printf was not being linked in!

#include <stdio.h>

int main(void)
{
printf("Hello, World!\n");
}


<sorry for OT-ness>:

.file "test.c"
.section .rodata
..LC0:
.string "Hello, World!"
.text
..globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
subl %eax, %esp
subl $12, %esp
pushl $.LC0
call puts
addl $16, %esp
leave
ret
.size main, .-main
.ident "GCC: (GNU) 4.0.3 20051201 (prerelease) (Debian 4.0.2-5)"
.section .note.GNU-stack,"",@progbits


--

John Devereux
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
C/C++ compilers have one stack for local variables and return addresses and then another stack for array allocations on the stack. Casey Hawthorne C Programming 3 11-01-2009 08:23 PM
x64 vs x86.. surprising results in performance (x86 better)? markm75 Windows 64bit 7 01-09-2008 06:41 PM
Why is there an x86 emu if a processor is x86-64? =?Utf-8?B?RWxsaW90IEh1ZGdpbnM=?= Windows 64bit 4 07-23-2006 11:52 PM
x86 Mac Laptop and x86 iMac now available Daniel NZ Computing 11 01-17-2006 12:11 PM
Is there a way with Linux x86 to report a way the current stack trace for a thread? kevin.hall@motioneng.com C++ 4 10-20-2005 09:43 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57