amd64 vs i386 assembly

I am working on a compiler that must generate FreeBSD-compatible amd64 assembly as output. The developer's manual has a fantastic section about system calls in i386 assembly. I was wondering if there were any differences between the calling conventions on i386 and amd64, and if there were, what they are. It would be especially helpful if there is a document that details any differences.

Thank you.
 
Subroutine/procedure calling conventions are covered by the ELF documentation, while I have no clue whether a syscall calling convention documentation even exists for AMD64 architecture... though I don't understand why a compiler would need to know the specifics about them, either (there are wrapper functions in the libc for this purpose).

EDIT: /even exists/even exists for AMD64 architecture/
 
xibo said:
Subroutine/procedure calling conventions are covered by the ELF documentation, while I have no clue whether a syscall calling convention documentation even exists for AMD64 architecture... though I don't understand why a compiler would need to know the specifics about them, either (there are wrapper functions in the libc for this purpose).

As far as why a compiler needs to be able to make system calls, it's very possible that I am misunderstanding something important. I thought that in order to do things like allocating memory and writing to stdout without going through libc (which I hoped to avoid) I needed to make a system call.

Am I wrong in thinking this? I am relatively new to FreeBSD and assembly in general (though I did a bit of it with linux, which decided to change everything with the transition to amd64).

I want to avoid libc as a fun challenge more than anything else, really, and if I were making production code that would obviously be the best choice.
 
AFAIK const data and bss are automatically reserved/defined by the executable loader while stack is assigned on demand by the page fault handler, which leaves heap section memory as the only thing left for manual allocation. Heap can be allocated with the sbrk(2) system call which is deprecated (I don't know what it's being replaced with) and the specifics can probably be reverse engineered from /usr/src/lib/libc/amd64/sys/sbrk.S (assuming your FreeBSD source is rooted at /usr/src).

While it's perfectly legal to avoid the libc, doing so will likely not provide an advantage.
 
  • Thanks
Reactions: jep
Whatever you do in a program you have to use system calls one way or another if you want to do any kind of I/O or allocate heap memory. The libc functions that implement the C standard library API are mostly just wrappers around the system calls.
 
  • Thanks
Reactions: jep
I guess that in that case, doing system calls without libc wouldn't really be fun or interesting as much as it would be a headache.

At this point, if I really wanted to do my own allocations on the heap, I would probably just reverse engineer libc's malloc, but it seems like it would be easier to just avoid this.

Thank you everyone.
 
Why avoid libc? If there's a bug in libc, we fix it and every dependent application is fixed. If you reimplement your own library, you've just doubled the maintenance required to fix memory management bugs, when using your compiler.
 
For a fun project, it is absolutely OK to go as far as you want. What's on the other side of that mountain? Let's go and see. So creating your own runtime can be fun, even if the only reason for it is that 'I can'.

The easiest approach I can think of now would be to create some 'hello world' program in C and then you can use gdb to "disassemble open" to see what the machine code there is. Repeat as needed for other functions you need.

May I also ask for what language your compiler is meant to be?
 
Back
Top