What is global _start in assembly language?

2019-03-08 15:32发布

问题:

This is my assembly level code ...

section .text
global _start
_start: mov eax, 4
        mov ebx, 1
        mov ecx, mesg
        mov edx, size
        int 0x80
exit:   mov eax, 1
        int 0x80
section .data
mesg    db      'KingKong',0xa
size    equ     $-mesg

Output:

root@bt:~/Arena# nasm -f elf a.asm -o a.o
root@bt:~/Arena# ld -o out a.o
root@bt:~/Arena# ./out 
KingKong

My question is What is the global _start used for? I tried my luck with Mr.Google and I found that it is used to tell the starting point of my program. Why cant we just have the _start to tell where the program starts like the one given below which produces a kinda warning on the screen

section .text
_start: mov eax, 4
        mov ebx, 1
        mov ecx, mesg
        mov edx, size
        int 0x80
exit:   mov eax, 1
        int 0x80
section .data
mesg    db      'KingKong',0xa
size    equ     $-mesg

root@bt:~/Arena# nasm -f elf a.asm
root@bt:~/Arena# ld -e _start -o out a.o
ld: warning: cannot find entry symbol _start; defaulting to 0000000008048080
root@bt:~/Arena# ld -o out a.o
ld: warning: cannot find entry symbol _start; defaulting to 0000000008048080

回答1:

global directive is NASM specific. It is for exporting symbols in your code to where it points in the object code generated. Here you mark _start symbol global so its name is added in the object code (a.o). The linker (ld) can read that symbol in the object code and its value so it knows where to mark as an entry point in the output executable. When you run the executable it starts at where marked as _start in the code.

If a global directive missing for a symbol that symbol will not be placed in the object code's export table so linker has no way of knowing about the symbol.

If you want to use a different entry point name than _start (which is the default), you can specify -e parametre to ld like:

ld -e my_entry_point -o out a.o


回答2:

A label is not explicitly global until you declare it to be global so you have to use the global directive.

The global label "_start" is needed by the linker, if there is no global _start address then the linker will complain because it cant find one. You didnt declare _start as a global so it is not visible outside that module/object of code so not visible to the linker.

This is the opposite of C where things are implied to be global unless you declare them to be local

unsigned int hello;
int fun ( int a )
{
  return(a+1);
}

hello and fun are global, visible outside the object, but this

static unsigned int hello;
static int fun ( int a )
{
  return(a+1);
}

makes them local not visible.

all local:

_start:
hello:
fun:
more_fun:

these are now global available to the linker and other objects

global _start
_start:
global hello
hello:
...


回答3:

_start is set by the default ld linker script

 ld -verbose a.o | grep ENTRY

outputs:

ENTRY(_start)

The ELF file format (and other object format I suppose), explicitly say which address the program will start running at through the e_entry header field.

ENTRY(_start) tells the linker to set that entry the address of the symbol _start when generating the ELF file from object files.

Then when the OS starts running the program (exec system call on Linux), it parses the ELF file, loads the executable code into memory, and sets the instruction pointer to the specified address.

The -e flag mentioned by Sedat overrides the default _start symbol.

You can also replace the entire default linker script with the -T <script> option, here is a concrete example that sets up some bare metal assembly stuff.



回答4:

global _start is just a label that points to a memory address.In the case of _start when it comes to ELF binaries it is the default label used that acts as the address where the program starts.

There is also main or _main or main_ is known to the C language, and is called by "startup code" which is "usually" linked to - if you're using C.

Hope this helps.



标签: assembly nasm