assembly - 简单的 hello world exec 是 10 KB
问题描述
我在 x86 nasm 汇编中做了一个简单的 Hello World 程序,但我不明白为什么最终的 exec 几乎是 10Ko。
nasm 版本:
NASM 版本 2.13.03 编译于 2018 年 4 月 1 日
ld版本:
GNU ld (GNU Binutils) 2.31.1
这是我的源代码:
; -------------------------------------------------------------
; Writes "Hello, World" to the console using only system calls.
; Runs on 64-bit Linux only.
; To assemble and run:
;
; nasm -f elf64 hello.asm
; ld hello.o -o hello
; ./hello
; or in one line
; nasm -felf64 hello.asm && ld hello.o -o hello && ./hello
;
; -------------------------------------------------------------
%define newline 0xA
%define nullchar 0x0
%define SYS_WRITE 1 ; system callcode for write
%define SYS_EXIT 60 ; system callcode for exit
%define STD_OUT 1
section .data
message db "Hello, World!", newline, nullchar
len_message equ $-message
section .text
;we must export the entry point to the ELF linker or
;loader. They conventionally recognize _start as their
;entry point. Use ld -e foo to override the default.
global _start
_start:
call .print
call .exit
.print:
mov rax, SYS_WRITE
mov rdi, STD_OUT ; we write text in the shell
mov rsi, message ; address of string to output
mov rdx, len_message ; number of bytes
syscall ; invoke kernel
ret ; return
.exit:
mov rax, SYS_EXIT
mov rdi, 0 ; exit code 0
syscall ; invoke kernel
当我用 nasm -f elf64 hello.asm 组装它时,我得到一个大小为 976 字节的 hello.o 文件。
当我将它与 ld hello.o -o hello 链接时,我得到一个大小为 8.9K 的 hello exec(我用 ls -lh 得到大小)。
为什么链接使最终的 exec 如此庞大?即使我使用删除调试数据的选项 (ld -s),我也只会丢失 500 个字节。
这是输出
readelf -a hello
:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x401000
Start of program headers: 64 (bytes into file)
Start of section headers: 8656 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 4
Size of section headers: 64 (bytes)
Number of section headers: 7
Section header string table index: 6
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .note.gnu.propert NOTE 0000000000400120 00000120
0000000000000020 0000000000000000 A 0 0 8
[ 2] .text PROGBITS 0000000000401000 00001000
0000000000000032 0000000000000000 AX 0 0 16
[ 3] .data PROGBITS 0000000000402000 00002000
000000000000000f 0000000000000000 WA 0 0 4
[ 4] .symtab SYMTAB 0000000000000000 00002010
0000000000000138 0000000000000018 5 9 8
[ 5] .strtab STRTAB 0000000000000000 00002148
0000000000000048 0000000000000000 0 0 1
[ 6] .shstrtab STRTAB 0000000000000000 00002190
000000000000003a 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x0000000000000140 0x0000000000000140 R 0x1000
LOAD 0x0000000000001000 0x0000000000401000 0x0000000000401000
0x0000000000000032 0x0000000000000032 R E 0x1000
LOAD 0x0000000000002000 0x0000000000402000 0x0000000000402000
0x000000000000000f 0x000000000000000f RW 0x1000
NOTE 0x0000000000000120 0x0000000000400120 0x0000000000400120
0x0000000000000020 0x0000000000000020 R 0x8
Section to Segment mapping:
Segment Sections...
00 .note.gnu.property
01 .text
02 .data
03 .note.gnu.property
There is no dynamic section in this file.
There are no relocations in this file.
The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
Symbol table '.symtab' contains 13 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000400120 0 SECTION LOCAL DEFAULT 1
2: 0000000000401000 0 SECTION LOCAL DEFAULT 2
3: 0000000000402000 0 SECTION LOCAL DEFAULT 3
4: 0000000000000000 0 FILE LOCAL DEFAULT ABS hello.asm
5: 0000000000402000 0 NOTYPE LOCAL DEFAULT 3 message
6: 000000000000000f 0 NOTYPE LOCAL DEFAULT ABS len_message
7: 000000000040100a 0 NOTYPE LOCAL DEFAULT 2 _start.print
8: 0000000000401026 0 NOTYPE LOCAL DEFAULT 2 _start.exit
9: 0000000000401000 0 NOTYPE GLOBAL DEFAULT 2 _start
10: 000000000040200f 0 NOTYPE GLOBAL DEFAULT 3 __bss_start
11: 000000000040200f 0 NOTYPE GLOBAL DEFAULT 3 _edata
12: 0000000000402010 0 NOTYPE GLOBAL DEFAULT 3 _end
No version information found in this file.
Displaying notes found in: .note.gnu.property
Owner Data size Description
GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0
Properties: x86 ISA needed: i486
解决方案
我想我找到了些东西。
在 ld 的 2.30 版本中添加了一个新标志,并且默认激活
2.30 中的变化:
- 添加 -z 单独代码以生成单独的代码 PT_LOAD 段。
如果我链接ld -z noseparate-code hello.o -o hello
二进制的大小为1032字节,比较合理。我不知道PT_LOAD是什么,但运行 hello world 程序看起来并不重要。
推荐阅读
- python - 如何使用 python_jwt 验证 firebase 令牌
- php - 在 PHPDoc 标准中键入提示水合对象
- java - springboot 忽略类路径中的 logback.xml
- python - 为下拉表发送带有指定值的 request.get
- swift - 快速为按钮组添加边框
- java - 如何从文本文件中读取前 3 个三位数?
- c++ - Interoperabilty between C and C++ atomics
- python - Python Tensor Flow Training-Value Error: Tensor must be from the same graph as Tensor
- spring-boot - 如何从组件访问头文件变量?
- android - 带有粘性标题和子标题的 Recyclerview