Page 1 of 1

Newlib questions

Posted: Mon Sep 26, 2011 9:25 am
by IanSeyler
A while back I ported Newlib to BareMetal OS (Instructions so far are here: http://code.google.com/p/baremetal/wiki/BuildingNewlib). Now I am looking to add to its functionality.

I hoping that someone else on here that has ported Newlib can answer my questions.

In crt0.s (or .c) I want to push argc and argv onto the stack. In what order is this done? More importantly what format should argv be in? Pointers to NULL-terminated strings?

Also where can I find details on what open(), close(), read(), and wirte() expect (mainly in regards to file operations).

Thanks,
-Ian

Re: Newlib questions

Posted: Mon Sep 26, 2011 9:55 am
by Solar
ReturnInfinity wrote:In crt0.s (or .c) I want to push argc and argv onto the stack. In what order is this done?
AFAIR, reverse order... but there are certainly ASM gurus around that can answer that one with confidence.
More importantly what format should argv be in? Pointers to NULL-terminated strings?
Yep, an array of C strings it is. (After all, that's what main() expects to find on the stack, now is it?)
Also where can I find details on what open(), close(), read(), and write() expect (mainly in regards to file operations).
Don't understand this as a RTFM reply, but I actually recommend the corresponding man pages. They are quite detailed, and sometimes point out holes in the generic POSIX docs (which would be the "standard" documentation otherwise.)

Re: Newlib questions

Posted: Mon Sep 26, 2011 10:58 am
by NickJohnson
Solar wrote:
ReturnInfinity wrote:In crt0.s (or .c) I want to push argc and argv onto the stack. In what order is this done?
AFAIR, reverse order... but there are certainly ASM gurus around that can answer that one with confidence.
At least on 32 bit x86 (assuming cdecl), that's definitely the case. For cdecl, the leftmost argument to the C function should be on the top of the stack before the "call". Note that if you're compiling your C code with GCC 4.5 or above, the stack has to be 16-byte aligned for the C function.

Edit: Hmm, maybe x86_64 doesn't use cdecl at all... based on this, it could be that GCC uses a register calling convention. I would check your compiler's ABI documentation to be sure.

Edit 2: fixed link.

Re: Newlib questions

Posted: Mon Sep 26, 2011 2:37 pm
by Owen
GCC uses the platform's calling convention. For most platforms, this is defined by the SystemV ABI. For Win32+ (AKA Win64, because Microsoft have a thing against putting the letters "64" in anything 64-bit) a different (simpler, but less efficient) register calling convention is used

Re: Newlib questions

Posted: Fri Sep 30, 2011 12:58 pm
by IanSeyler
Thanks for the replies everyone. I tried passing the values (argc, and the argv[*] pointers) via the stack but it didn't work. I also took a look at the System V ABI and even it shows pushing the values to the stack. I traced the program execution under Bochs and it looks like it is pulling out the values using a different method.

On program start I need to put argc in the RDI register. argv[*] requires a pointer table with the table address in RSI.

Not what I was expecting but it works correctly now. I don't know if this is a newlib thing or it could be due to me using flat binaries for the compiled programs.

As for open(), read(), etc I will take a look at the POSIX docs.

Thanks,
-Ian

Re: Newlib questions

Posted: Fri Sep 30, 2011 1:19 pm
by jnc100
According to my version of the System V ABI (AMD64 processor supplement) the behaviour you are seeing is entirely expected. See section 3.2.3 'Parameter passing'. Arguments of type _Bool, char, short, int, long, long long (all signed + unsigned) and pointers are in the 'INTEGER' class. Arguments in this class are passed in the order rdi, rsi, rdx, rcx, r8 and r9 and then finally on the stack once these registers are used up.

Regards,
John.