phoenix wrote:
> Hello guys,
> I am a complete newbie who is trying to learn assembly. I am using
> NASM and working on Linux.
> I have written a (very) simple program that calculates ah+al.
> Here it is the code:
>
> -----------------------------------------------
> ; this file is called ass.s
What would you have named it if it divided by two? :)
> segment .data
> number1 db 5
> number2 db 7
>
> segment .text
> global prog
> prog:
> push ebp
> mov ebp,esp
> xor eax,eax
> mov al,[number1]
> mov ah,[number2]
> add al,ah
> xor ah,ah
> pop ebp
> ret
>
> -------------------------------------------------
>
> So I type in the terminal: nasm -f elf ass.s -o ass.o
> and then I type: gcc ass.o -o as***e
>
> An error message appears:
> /usr/lib/gcc/i486-linux-gnu/4.1.2/../../../../lib/crt1.o: In function
> `_start':
> (.text+0x18): undefined reference to `main'
> collect2: ld returned 1 exit status
>
>
> If the label (in the program) is called main (and not prog), there's
> no error message.
> If the label is called start, the error message appears again.
>
> My question is: can I choose whatever label names in my program,
> without having all these error messages? Or am I forced to always
> insert a label called "main" in my code?
>
> Thank you and sorry for my english!
Nothing special about English - the CPU doesn't speak it! :)
This is a good question (in any language). In general, you can use any
names you want, but certain names are "known" to certain parts of the
toolchain (including Nasm - don't call a procedure "eax", for example).
By default, gcc will link some "startup" code against the modules you
give it. This "startup code" (crt0.o or somesuch) calls "main" - so it
has to be there, somewhere! You can tell gcc "--nostartfiles" (or
somesuch) to eliminate this default behavior, if you want to...
You might want to write a "ass_c.c" to call "prog" (since you've
declared it "global")...
void prog (void);
int main()
{
prog();
return 0;
}
That would be another way to shut gcc up.
Without the underscore, "start" is "nothing special", but "_start" is
known to ld as the default entrypoint - where the loader will transfer
control to our code. The "startup code" includes this label, so if
you've linked that in, and also had a "_start" label in your code, ld
would complain about finding it twice. But ld expects to find it
*somewhere*, and will complain if it doesn't. Hard to please! :) You can
override "_start" as the "known" entrypoint with "-e:otherentry" on the
command line to ld... if you think there's any point...
So "main" and "_start" are the two "special" labels you have to worry
about. If you're *not* using C, you can use "main" freely - I try to
avoid it, unless it's a "real C main", since it may confuse humans, but
Nasm and ld don't care about it...
You *must* have an entrypoint - ld picks a default, if it can't find
"_start", which may or may not be right. Doesn't *need* to be called
"_start", but... what's the point of calling it something else!
So, we could say gcc provides "_start" and expects you to provide
"main". There isn't really much point in involving gcc at all, for
something as simple as this. We could just start with "_start", and exit
with "sys_exit", returning the "answer" in bl. (I'm fond of saying we
return an exitcode in ebx, but it's really just bl!) Like so:
; assemble: nasm -f elf myprog.asm
; link: ld -o myprog myprog.o
; run: ./myprog
; observe: echo $?
global _start
section .text
_start:
mov bl, 5
add bl, 7
mov eax, 1 ; __NR_exit
int 80h
;----------------
You can easily add variables number1 and number2 back in - just like
you've got it (except return in bl, not al) for "example 2", if you want.
When we get to adding two floating-point numbers... it becomes *really*
handy to be able to use "printf" to display the results! You may want
something a little more flexible than "echo $?" to communicate with the
user sooner than that. We can provide that, with or without C.
Or perhaps you want to get into interfacing with C right from the start.
There are a few "rules", besides "main" being special... caller cleans
up stack... ebx, esi, edi, and (obviously?) ebp have to be preserved
across calls (including "main"!)... and we can expect the same from C
when we call C (this implies that ecx and edx may be trashed on ya!!!).
Result in eax, usually (float???). Printf expects floats to be passed as
doubles, even if ya call 'em "float". I'm probably forgetting some...
For a start, try replacing "prog" with "main" in your file... can you
see the correct result with "echo $?". Looks to me like it'd work, but I
haven't tried it. Figured I'd leave that for you. :)
Best,
Frank


|