Author Topic: still can't link hello.asm  (Read 16481 times)

Penfold

  • Guest
still can't link hello.asm
« on: July 26, 2007, 11:51:49 AM »
getting more and more confused

I've compiled the code below. Or at least I think I have as I don't get any complaints when I type in 'nasm -f macho -l hello.lst  hello.asm' and press return.

then I try to do 'gcc -o hello  hello.o'

and I get:

/usr/bin/ld: Undefined symbols:
_main
collect2: ld returned 1 exit status

the '_main' in the error message doesn't seem to refer to the '_main' in the program as I get the same message even when I delete it from the program or replace it with start.

what does this mean? What am I doing wrong?

pedro

Penfold

  • Guest
Re: still can't link hello.asm
« Reply #1 on: July 26, 2007, 11:52:53 AM »
oops... forgot.

here's the code

;  hello.asm  a first program for nasm for Linux, Intel, gcc
;  AND MACOSX!
; assemble:     nasm -f macho -l hello.lst  hello.asm
; link:        gcc -o hello  hello.o
;  or is it gcc hello.o -o hello ; ./hello ; echo $?
; run:         hello
; output is:  Hello World

SECTION .data          ; data section
msg:   db "Hello World",10   ; the string to print, 10=cr
len:   equ $-msg          ; "$" means "here"
                        ; len is a value, not an address

SECTION .text      ; code section
     global main       ; make label available to linker
_main:               ; standard  gcc  entry point
   mov   edx,len      ; arg3, length of string to print
   mov   ecx,msg      ; arg2, pointer to string
   mov   ebx,1      ; arg1, where to write, screen
   mov   eax,4      ; write sysout command to int 80 hex
   int   0x80      ; interrupt 80 hex, call kernel

mov   ebx,0      ; exit code, 0=normal
   mov   eax,1      ; exit command to kernel
   int   0x80      ; interrupt 80 hex, call kernel

Penfold

  • Guest
Re: still can't link hello.asm
« Reply #2 on: July 26, 2007, 01:44:51 PM »
but now I can do it.

me so happy!

nobody

  • Guest
Re: still can't link hello.asm
« Reply #3 on: July 26, 2007, 02:11:41 PM »
global main
_main:

Looks to me like you'd better decide whether you want an underscore on "main" or not! I think MacOS *does* want an underscore.

The next problem you're going to encounter is that the code you've got is for Linux, and won't work on MacOS (AFAIK). You want to push the parameters, not put 'em in ebx, ecx, edx... And then you need to call a "stub" containing "int 80h"/"ret", *or* push an extra "dummy" parameter and do the "int 80h" in line. After the "int 80h", you'll need to "remove" the parameters from the stack. "add esp, byte 4 * number_of_parameters" That would include the "dummy" parameter, if you don't do the call and return (which *I* wouldn't...)

You don't need to involve gcc unless you need it for something. It knows where the bodies are buried, and so knows the correct command line to pass to ld. If you're using this, you may want it - although you can discover the command line to ld and get along without gcc... unless you're actually compiling something with it.

Since you're using the int 80h interface exclusively, you really have no need for any C code at all. You could just:

global _start

section .data
msg db "hello", 10
msg_len equ $ - msg

section .text
_start:
push msg_len
push msg
push 1 ; stdout
mov eax, 4 ; __NR_write
push eax   ; or any value
int 80h
add esp, 4 * 4

push 42  ; exit code
mov eax, 1 ; __NR_exit
push eax ; or any value
int 80h

Assemble with:

nasm -f macho myprog.asm

Link with:

ld -o myprog myprog.o

Now... "_start" is "known" to Linux ld as the default entrypoint. This may not be true of MacOS. If your ld complains about not finding the entrypoint, try adding "-e_start" to the command line. You could, of course, use some other name - even "main". I like to save "main" for an entrypoint that's called from crt0.o. C cares about the name "main" - it's just another symbol to Nasm...

My example exits with 42 instead of the usual 0. In Linux, we can see the exit code by typing "echo $?", which you mention in your comments. If this also works for MacOS, which I suspect it does, it can be used as a temporary answer to the question "how do I display a number?" Doing "add eax, ebx" ain't brain surgery, but how do you see the result? Calling "write" with eax as a buffer isn't going to work! "Just call printf" is one answer, your own "itoa" is another. This may be easier for beginners - even though it's only good for a byte.

Well, I'm working completely "blind" here, since I don't have a Mac to test anything on. I count on you guys for feedback, and to tell me when I'm advising you wrong!

Best,
Frank