NASM - The Netwide Assembler

NASM Forum => Using NASM => Topic started by: robbje on March 29, 2010, 05:30:51 AM

Title: Calling assembly functions from C
Post by: robbje on March 29, 2010, 05:30:51 AM
Hi all,

I'm sure this was answered somewhere else here already, couldn't find
anything though. Following Dr. Carter's book i ran into a problem, I
can't resolve.

asmfunc.asm:
Code: [Select]
segment .text
global _start
_start:
mov eax, 0
ret

main.c
Code: [Select]
int main(int argc, char* argv[])
{
        _start();
        return 0;
}

Makefile:
Code: [Select]
all:
        nasm -f elf asmfunc.asm -o asmfunc.o
        gcc -c main.c
        gcc -o asmfunc main.o asmfunc.o


./asmfunc gives segfault. why?

Regards,
robbje
Title: Re: Calling assembly functions from C
Post by: robbje on March 29, 2010, 05:44:41 AM
Is there no edit option here?

Anyways:

global _start
_start:

does not link:
Code: [Select]
asmfunc.o: In function `_start':
asmfunc.asm:(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/i486-linux-gnu/4.3.2/../../../../lib/crt1.o:(.text+0x0): first defined here

deleting 'global _start' gives aforementioned segfault

edit: ah, top right...(sometimes)
Title: Re: Calling assembly functions from C
Post by: Frank Kotler on March 29, 2010, 06:21:43 AM
Yeah, "_start" is the default entrypoint. Call it something else. Looks like it should work, otherwise. You might need to "prototype" your asm function in the C file to quiet warnings...

Code: [Select]
#include <stdio.h>
int cpu_vendor(char *dest);

int main(){
    char buf[13];
    int cpuid_max_level;
   
    cpuid_max_level = cpu_vendor(buf);
    printf("vendor = %s\nmaxlevel = %d\n", buf, cpuid_max_level);
    return (0);
    };

Code: [Select]
; nasm -f elf cpuvendor.asm
; nasm -f win32 --prefix _ cpuvendor.asm ???

; tell ld about us (via the .o file)
global cpu_vendor

cpu_vendor:
; C expects to have these regs preserved
    push edi
    push ebx
; our parameter, the buffer, is "up the stack",
; 4 for ebx, 4 for edi, 4 for return address = 12
    mov edi, [esp + 12]
    xor eax, eax
    cpuid
; with eax = 0, cpuid returns the vendor string
; in ebx, edx, ecx (why???), and the maximum level
; in eax (our return value). With eax greater than
; this maximum level (for this implementation of cpuid)
; cpuid returns unexpected results - 16 cores in this
; clunker? I don't think so!

; stuff the vendor string into our destination buffer
    mov [edi], ebx
    mov [edi + 4], edx
    mov [edi + 8], ecx
; don't forget to zero-terminate it!
    mov byte [edi + 12], 0
; restore caller's regs
    pop ebx
    pop edi
; we're done!
    ret

Something like that...

Best,
Frank

   
Title: Re: Calling assembly functions from C
Post by: robbje on March 29, 2010, 06:48:27 AM
serious facepalming incoming!

thanks a lot