_start 的默认值

Default value of _start

假设我有以下汇编程序:

.globl _start
_start:
    mov , %eax
    int [=10=]x80

我 assemble/link 它与:

$ as file.s
$ ld a.out -o a

这将运行很好,return状态码0到linux。但是,当我删除行 .globl start 时,出现以下错误:

ld: warning: cannot find entry symbol _start; defaulting to 0000000000400078

0000000000400078是什么意思?而且,如果 ld 期望 _start 符号进入,为什么甚至有必要声明 .globl _start

However, when I remove the line .globl _start ...

.globl 行表示名称 _start 在文件 file.s 之外“可见”。如果删除该行,名称 _start 只能在文件 file.s 中使用,而在更大的程序(包含多个文件)中,您甚至可以在多个文件中使用名称 _start

(这类似于 C/C++ 中的 static 变量:如果您从 C 或 C++ 生成汇编代码,则真正的全局变量和 static 变量之间的区别在于全局变量有 .globl 行, static 变量没有 .globl 行。如果你熟悉 C,你就会知道 static 变量不能用于其他文件。)

链接器 (ld) 也不能使用名称 _start 如果它只能在文件内部使用。

What does 0000000000400078 mean?

显然0x400078是你程序第一个字节的地址。如果没有找到名为 _start 的符号,ld 假定程序从第一个字节开始。

... why is it even necessary to declare .globl _start?

不保证 _start 位于程序的第一个字节。

反例:

.globl _start

write_stdout:
    mov , %eax
    mov , %ebx
    int [=10=]x80
    ret

exit:
    mov , %eax
    mov [=10=], %ebx
    int [=10=]x80
    jmp exit

_start:
    mov $text, %ecx
    mov $(textend-text), %edx
    call write_stdout
    mov $text2, %ecx
    mov $(textend2-text2), %edx
    call write_stdout
    call exit

text:
    .ascii "Hello\n"
textend:
text2:
    .ascii "World\n"
textend2:

如果删除 .globl 行,ld 将无法找到 _start: 行并假设您的程序从第一个字节开始 - 即 write_stdout:行!

... 如果您在一个较大的程序中有多个 .s 文件(或者甚至是 .s.c.cc 的组合),您不需要控制哪个代码位于程序的第一个字节!