Page 1 of 1

undefined reference in .S file

Posted: Mon Jan 21, 2008 4:14 am
by crasher
I wrote a piece of assembly code(start.S) which is listed below.
I tried both
gcc -c start.S
and
start.o:start.S multiboot.h
gcc -c start.S -o start.o

I got error "undefined reference to 'MULTIBOOT_HEADER_MAGIC'"

Does anybody know how to solve this?
FYI multiboot.h is in the same directory as start.S and makefile

#include <multiboot.h>

.text
.global start
start:
jmp __start

.align 4
.long MULTIBOOT_HEADER_MAGIC
....

Posted: Mon Jan 21, 2008 4:24 am
by pini
Did you try

Code: Select all

.long $MULTIBOOT_HEADER_MAGIC
?

Otherwise, try passing only the preprocessor over your .S file to see what happens

undefined reference in .S file

Posted: Mon Jan 21, 2008 4:34 am
by crasher
I tried just now.
It worked in that the error changed from
"undefined reference ..." to
"no such instruction: typedef struct{'"

It seems the assembler does not recoginze the c instruction.

undefined reference in .S file

Posted: Mon Jan 21, 2008 5:00 am
by crasher
When I used gcc -D__ASSEMBLY__ -c start.S,
the "no such instruction.." error and "undefined
reference to MULTIBOOT_HEADER_MAGIC" were gone.

I did not use $MULTIBOOT_HEADER_MAGIC

What is '$' for? I saw some assembly code precedes
constants/macros with '$', such as xen's x86_32.S
while I don't need this in my case.

Posted: Mon Jan 21, 2008 6:36 am
by pini
Your second error seems quite strange.
I assumed that MULTIBOOT_HEADER_MAGIC was

#define MULTIBOOT_HEADER_MAGIC 0x1BADB002

or something like that.

The '$' sign is used to prefix integer constants in the AT&T assembly syntax.
For instance:

movl $0x10,%eax ; <=> mov eax,0x10 in intel syntax

puts the integer constant 0x10 in eax, while

movl 0x10,%eax ; <=> mov eax,[0x10] in intel syntax

puts the value at memory location 0x10 in eax.

Posted: Mon Jan 21, 2008 7:10 am
by Solar
For ease of reference, this are the relevant parts of multiboot.h crasher is talking about. (Note that multiboot.h is (C) 1999,2001 FSF Inc., falls under GPL, yadda yadda...)

Code: Select all

     /* Macros. */
     
     /* The magic number for the Multiboot header. */
     #define MULTIBOOT_HEADER_MAGIC          0x1BADB002

     /* ... */
     
     #ifndef ASM
     /* Do not include here in boot.S. */
     
     /* Types. */
     
     /* The Multiboot header. */
     typedef struct multiboot_header
     {
       unsigned long magic;
       unsigned long flags;
       unsigned long checksum;
       unsigned long header_addr;
       unsigned long load_addr;
       unsigned long load_end_addr;
       unsigned long bss_end_addr;
       unsigned long entry_addr;
     } multiboot_header_t;
     
     /* ... */
     
     #endif /* ! ASM */
The statement...

Code: Select all

.long MULTIBOOT_HEADER_MAGIC
...inserts the value 0x1BADB002 at the current position. What does not happen is that a symbol of that name is inserted.

You did cut your code short, so I don't know if you referred to this symbol later on.

As for the "$", it is the qualifier for immediate addressing (constant), as opposed to direct addressing (pointer).

$4 is the value 4.
4 is the value at address 4.

And if you take a look at the header, you will see that the C instructions are commented out if "ASM" is defined. 'as' doesn't know how to handle them.

undefined reference in .S file

Posted: Mon Jan 21, 2008 7:46 pm
by crasher
Thanks for your help.
I found '$' precedes an immediate constant operand such as

Code: Select all

movl $0x10, eax 
In the case assgining a memory, we use naked constants, i.e.,

Code: Select all

.long 0x10 
instead of .long $0x10

Am I right?

Posted: Tue Jan 22, 2008 2:23 am
by JamesM
Yes.