You are not logged in.
Is it possible to use 32-bit assembly language to call C functions in 64-bit linux?
Background: I'm learning 32-bit AT&T syntax Linux assembly language programming. The only reason for 32-bit is that's what's covered in the book I have. Some simple examples assemble, link, and execute in Arch 64 using GNU either gcc or as + ld -- with no changes either to code or command line flags.
The problem: I'm having trouble with C function calls. Even after replacing register names (e.g., edi -> rdi) and mnemonics (e.g., movl -> movq), I find that a program which calls printf and exit never prints anything, and never returns. Hence the question.
I can post code if needed (it's on my other machine), but this is really more of a general question -- is it possible to call C functions in Arch 64 using 32-bit AT&T syntax, and if so, how.
Thanks!
Offline
this is really more of a general question -- is it possible to call C functions in Arch 64 using 32-bit AT&T syntax, and if so, how.
That wasn't well put. What I meant is, can it be done similarly to what worked for IA-32. Or, for example, is it no longer possible to push function arguments onto the stack.
A web search seemed to indicate that IA-64 implementations of C library functions get their arguments from registers -- but I'd need to see a simple example of how that's done. I am studying assembler output from a simple C example, but without explanation it's still a little obscure.
Thanks.
Offline
.
Last edited by fumbles (2020-09-26 11:37:48)
Offline
Not even a typo, just confusion. The CPU is an Intel Core 2 Duo -- so it's actually x86-64.
I realize that NASM is not GAS, but checking the NASM manual helped me figure out a few things about calling 64-bit C functions:
http://www.nasm.us/doc/nasmdo11.html
It took a while to figure out how to correctly call printf. The missing clue was here:
http://www.mit.edu/~6.035/handouts-2007 … convention
printf reads the number of variable arguments from %rax. In this example, printf is called with no variable arguments:
# c_functions.s - Calls 64-bit C functions putchar, printf, and exit
.section .data
a:
.byte 'a'
newline:
.byte '\n'
hello:
.asciz "hello, world\n"
.section .text
.globl main
main:
movq a, %rdi # used as argument for putchar
call putchar
movq newline, %rdi # used as argument for putchar
call putchar
movq $hello, %rdi # first argument for printf (i.e., the format string)
movq $0, %rax # number of variable arguments for printf
call printf
movq $0, %rdi
call exit
For simplicity, I compiled and linked with gcc (in other words, I let gcc figure out how to properly call as and ld):
gcc c_functions.s
If I can figure out how to pass variable arguments to printf, I'll post that. Based on the MIT reference linked above, it sounds like those arguments would be passed in SSE registers.
Offline
Here's an example of using registers to pass multiple arguments to printf. As far as I can tell, the value in %eax can remain zero until argument registers have been used up. I'm not yet sure how to pass a variable number of arguments on the stack. Possibly it would be in a structure.
.section .data
format_string:
.asciz "Vendor ID: %s"
.section .bss
.lcomm vendor_id, 12
.section .text
.globl main
main:
# Get vendor ID into registers ebx, edx, and ecx:
movl $0, %eax
cpuid
# Fill vendor_id buffer with data from registers:
movl $vendor_id, %edi
movl %ebx, (%edi)
movl %edx, 4(%edi)
movl %ecx, 8(%edi)
# Use registers to pass arguments to C functions:
movl $format_string, %edi
movl $vendor_id, %esi
movl $0, %eax
call printf
call exit
The 32-bit original on which this is based is available for download from Richard Blum's publisher:
Offline