You are not logged in.

#1 2009-07-19 13:54:14

mfisher_ix
Member
Registered: 2009-05-08
Posts: 5

Using C functions from IA-32 assembly language

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

#2 2009-07-19 14:26:49

mfisher_ix
Member
Registered: 2009-05-08
Posts: 5

Re: Using C functions from IA-32 assembly language

mfisher_ix wrote:

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

#3 2009-07-20 03:45:28

fumbles
Member
Registered: 2006-12-22
Posts: 246

Re: Using C functions from IA-32 assembly language

.

Last edited by fumbles (2020-09-26 11:37:48)

Offline

#4 2009-07-21 01:08:36

mfisher_ix
Member
Registered: 2009-05-08
Posts: 5

Re: Using C functions from IA-32 assembly language

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

#5 2009-07-21 04:26:39

mfisher_ix
Member
Registered: 2009-05-08
Posts: 5

Re: Using C functions from IA-32 assembly language

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:

http://www.wrox.com/WileyCDA/WroxTitle/ … NLOAD.html

Offline

Board footer

Powered by FluxBB