【问题标题】:Default value of _start_start 的默认值
【发布时间】:2020-12-12 12:37:04
【问题描述】:

假设我有以下汇编程序:

.globl _start
_start:
    mov $1, %eax
    int $0x80

我将它组装/链接到:

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

这样就可以正常运行,并将状态码0返回给linux。但是,当我删除 .globl start 行时,我收到以下错误:

ld:警告:找不到入口符号_start;默认为0000000000400078

0000000000400078 是什么意思?而且,如果ld 需要_start 符号进入,为什么还要声明.globl _start

【问题讨论】:

    标签: c assembly x86 ld att


    【解决方案1】:

    但是,当我删除行 .globl _start ...

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

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

    链接器 (ld) 也不能使用名称 _start,如果它只能在文件中使用的话。

    0000000000400078 是什么意思?

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

    ...为什么还要声明.globl _start

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

    反例:

    .globl _start
    
    write_stdout:
        mov $4, %eax
        mov $1, %ebx
        int $0x80
        ret
    
    exit:
        mov $1, %eax
        mov $0, %ebx
        int $0x80
        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 的组合),则您无法控制哪个代码位于程序的第一个字节!

    【讨论】:

    • 酷,很好的回答,非常感谢!一个问题:如果没有定义.globl,我将如何使用ld 输入特定符号?例如,类似(来自您上面的示例)$ ld -enter="exit" file.s 在这种情况下,脚本不会执行任何操作,只是退出。最后,为什么jmp exitexit 部分的末尾?
    • @samuelbrody1249 您可以使用-e 定义与_start 不同的入口点(例如:ld -e begin ...)。但是,在这种情况下,您必须使用.globl 声明另一个符号。根本不使用.globl,你几乎没有机会。 jmp exit 是一种习惯:在使用 Linux 之前,我使用过另一个操作系统,其中“退出”系统调用(在 Linux 中:eax=1)有时会失败并且必须重复。
    • 知道了,谢谢。所以换句话说,在被链接的程序集文件中至少有一个符号是.globl,对吧?
    • @samuelbrody1249 不一定,但没有任何全局符号不会很有用。我可以想到的一个例子是使用.comment 部分插入版权信息。在这种情况下,提供此.comment 部分的文件可能不会提供全局符号。也就是说,我建议您熟悉 GNU ld 手册。
    • @samuelbrody1249 .globl 在 gnu 汇编器中只是使标签成为全局标签,以便它在该对象之外可见(因此可以在需要时链接或以其他方式查看它)。 _start 是链接器在 gnu 世界中寻找的一个特殊标签。即使您没有全局标签,您的代码仍然会被链接,这只是意味着您要么知道如何以不典型的方式获取该数据。 (链接到特定地址,然后在该地址不使用标签访问它)。或者您只是在未使用的二进制文件中添加内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-12
    • 2019-07-05
    • 2015-05-22
    • 2011-01-24
    • 1970-01-01
    • 2013-12-25
    • 2015-03-13
    相关资源
    最近更新 更多