You are not logged in.

#1 2009-12-03 19:21:44

archnoobie
Member
Registered: 2009-10-29
Posts: 33

Assembly and C

I'm trying to learn a little bit about assembly and such, so I made a multi-language program to figure out a little bit. It's very simplistic, but it accomplished what I want for the most part.
Here is what I wrote mix_asm.asm:

section .data
new_line    db      0xa
nl_len      equ     $ - new_line

section .text

            global  print_str

print_str:
            ;prologue
            push    ebp
            mov     ebp,esp

            push    eax
            push    ebx
            push    ecx
            push    edx

            mov     ecx,[ebp+8]
            push    ecx
            call    str_length

            mov     edx,eax
            mov     ecx,[ebp+8]
            mov     ebx,1
            mov     eax,4
            int     0x80

            call    print_nl

            ;epilogue
            pop     edx
            pop     ecx
            pop     ebx
            pop     eax
            
            mov     esp,ebp
            pop     ebp

            ret

str_length:
            ;prologue
            push    ebp
            mov     ebp,esp

            push    ebx
            push    ecx

            mov     ecx,0
            mov     ebx,[ebp+8]

while_1:
            cmp     word [ebx+ecx],0x0
            je      while_1_end

            add     ecx,1

            jmp     while_1
while_1_end:

            mov     eax,ecx

            ;epilogue
            pop     ecx
            pop     ebx
            
            mov     esp,ebp
            pop     ebp
            ret

print_nl:
            ;prologue
            push    ebp
            mov     ebp,esp

            push    eax
            push    ebx
            push    ecx
            push    edx

            mov     edx,nl_len
            mov     ecx,new_line
            mov     ebx,1
            mov     eax,4
            int     0x80
            
            ;epilogue
            pop     edx
            pop     ecx
            pop     ebx
            pop     eax
            
            mov     esp,ebp
            pop     ebp
            ret

and mix_c.c

/* test asm linking in c for *nix */
extern void print_str (char*);

int main ()
{
    print_str( "Hello world!" );
    return 0;
}

Now then, I can get it to work using elf format through nasm and linking with gcc. If I link with ld (ld -e main -o mix mix_asm.o mix_c.o) though, it returns with a segmentation fault. After executing through the end of the c:main function, it returns to address 0x1 (found using gdb), and I don't understand why. Is it something missing from the linker? A less pressing question, is there a way to get it to successfully link without using the elf format option in nasm? I'd greatly appreciate any help anyone can offer.

Offline

#2 2009-12-03 21:07:55

tavianator
Member
From: Waterloo, ON, Canada
Registered: 2007-08-21
Posts: 858
Website

Re: Assembly and C

- First point to make: you do not need to save eax, ecx, edx, and esp in print_str.  Only ebx, esi, edi, and ebp need to be preserved.
- At while_1, you should be comparing the byte at [ebx+ecx] to 0, not the word.

You need the ELF option to nasm because otherwise it just produces `bin' format output, which won't link into an ELF executable.

And finally the reason it segfaults: ld with -emain treats main() as an entry point, which it actually isn't.  With main() as your entry point, when it hits the "return 0;", it will try to jump to whatever address is on the stack behind ebp, which is 0x1 for some reason.  GCC will correctly link in the default C runtime (crt{1,i,n}.o among others), which actually call the main() function, whereas ld won't.  gcc -v gives a good idea of how gcc is calling the linker.

Offline

Board footer

Powered by FluxBB