汇编语言中的全局_start是什么?

vik*_*cks 23 assembly nasm

这是我的汇编级代码......

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
Run Code Online (Sandbox Code Playgroud)

输出:

root@bt:~/Arena# nasm -f elf a.asm -o a.o
root@bt:~/Arena# ld -o out a.o
root@bt:~/Arena# ./out 
KingKong
Run Code Online (Sandbox Code Playgroud)

我的问题是全球_start用于什么?我和Mr.Google试了一下运气,我发现它用来说明程序的起点.为什么我们不能_start告诉程序在哪里开始,如下面给出的那个在屏幕上产生一种警告

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
Run Code Online (Sandbox Code Playgroud)

Sed*_*glu 37

global指令是NASM特定的.它用于将代码中的符号导出到生成的目标代码中的位置.在此处标记_start符号全局,因此其名称将添加到目标代码(a.o)中.linker(ld)可以读取目标代码中的该符号及其值,以便它知道在输出可执行文件中将其标记为入口点的位置.当您运行可执行文件时,它将从_start代码中标记的位置开始.

如果global符号缺少指令,则该符号不会放在目标代码的导出表中,因此链接器无法知道该符号.

如果要使用不同的入口点名称_start(默认值),可以将-e参数指定为ld,如:

ld -e my_entry_point -o out a.o
Run Code Online (Sandbox Code Playgroud)

  • @vikkyhacks,原因是目标代码中不会放置任何符号,除非您专门为它们添加“global”指令。否则它们都被视为本地指令并在组装过程中被丢弃。 (3认同)
  • `_start`只是默认情况下的一个"知道".`ld -o out ao -e _main`会起作用. (2认同)
  • 我建议在您的示例中使用 `ld -e my_entry_point`。使用 C 编译器生成的 `main()` 通常不会这样做,所以使用 `_main` 只会让那些还不了解所有部分如何组合在一起的人感到困惑。 (2认同)

old*_*mer 5

在声明标签为全局标签之前,该标签不是显式全局的,因此必须使用全局指令。

链接器需要全局标签“ _start”,如果没有全局_start地址,则链接器会抱怨,因为找不到。您没有将_start声明为全局变量,因此它在该代码模块/对象之外不可见,因此对链接程序不可见。

这与C相反,除非您声明它们是局部的,否则隐含事物是全局的

unsigned int hello;
int fun ( int a )
{
  return(a+1);
}
Run Code Online (Sandbox Code Playgroud)

问候和乐趣是全局的,在对象外部可见,但这

static unsigned int hello;
static int fun ( int a )
{
  return(a+1);
}
Run Code Online (Sandbox Code Playgroud)

使它们在本地不可见。

所有本地:

_start:
hello:
fun:
more_fun:
Run Code Online (Sandbox Code Playgroud)

这些现在对链接器和其他对象全局可用

global _start
_start:
global hello
hello:
...
Run Code Online (Sandbox Code Playgroud)

  • @vikkyhacks,我猜您可以将汇编中的标签视为 C 上下文中的“静态”符号,至少在默认情况下是这样。也就是说,它们只能在文件/翻译单元范围内使用。使用 `.global` 定义标签会使汇编器将其导出(将其添加到对象的符号表中),以便链接器稍后可以在其他翻译单元中找到它(或在您的情况下用于程序启动)。 (3认同)

Cir*_*四事件 5

_start被默认的 Binutils 的ld链接器脚本用作入口点

我们可以使用以下命令查看该链接描述文件的相关部分:

 ld -verbose a.o | grep ENTRY
Run Code Online (Sandbox Code Playgroud)

输出:

ENTRY(_start)
Run Code Online (Sandbox Code Playgroud)

ELF文件格式(我想和其他对象格式),明确地说,项目将开始通过运行的地址e_entry头字段。

ENTRY(_start)告诉链接器在_start从目标文件生成 ELF 文件时将该条目设置为符号的地址。

然后当操作系统开始运行程序(Linux 上的exec系统调用)时,它会解析 ELF 文件,将可执行代码加载到内存中,并将指令指针设置为指定地址。

Sedat-e提到的标志会覆盖默认符号。_start

您还可以使用该-T <script>选项替换整个默认链接器脚本,这是一个设置一些裸机组件的具体示例

.global 是一个汇编指令,用于在 ELF 文件中将符号标记为全局

ELF 文件包含每个符号的一些元数据,指示其可见性。

观察这一点的最简单方法是使用nm工具。

例如在 Linux x86_64 GAS 独立的 hello world 中:

电源

.text
.global _start
_start:
asm_main_after_prologue:
    /* write */
    mov $1, %rax   /* syscall number */
    mov $1, %rdi   /* stdout */
    lea msg(%rip), %rsi  /* buffer */
    mov $len, %rdx /* len */
    syscall

    /* exit */
    mov $60, %rax   /* syscall number */
    mov $0, %rdi    /* exit status */
    syscall
msg:
    .ascii "hello\n"
    len = . - msg
Run Code Online (Sandbox Code Playgroud)

GitHub 上游

编译并运行:

gcc -ffreestanding -static -nostdlib -o main.out main.S
./main.out
Run Code Online (Sandbox Code Playgroud)

nm 给出:

00000000006000ac T __bss_start
00000000006000ac T _edata
00000000006000b0 T _end
0000000000400078 T _start
0000000000400078 t asm_main_after_prologue
0000000000000006 a len
00000000004000a6 t msg
Run Code Online (Sandbox Code Playgroud)

man nm告诉我们:

如果是小写,符号通常是本地的;如果大写,则符号是全局的(外部的)。

所以我们看到它_global在外部可见(大写T),但msg我们没有标记为.global不是(小写t)。

如果看到多个具有相同名称的全局符号,链接器就会知道如何炸毁,或者更聪明的事情是看到更奇特的符号类型

如果我们不标记_start为全局,ld就会变得悲伤并说:

找不到入口符号 _start


归档时间:

查看次数:

29153 次

最近记录:

6 年,8 月 前