You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何ARM64汇编Hello World程序在Mac M1上体积达17KB?

关于ARM64 macOS汇编程序体积与冗余内容的解答

一、先明确两类程序的本质差异

你之前写的x86 NASM Hello World是实模式裸机程序:直接通过BIOS中断调用硬件输出,完全不需要操作系统介入,用nasm -f bin生成的是纯二进制指令,没有任何文件格式额外开销,体积自然就是指令对应的字节数。

而ARM64 macOS下用as编译的是用户态可执行程序,必须符合macOS的Mach-O文件格式规范,依赖系统加载器和系统服务,那些你觉得“冗余”的内容都是系统运行和格式要求的必要组成部分。

二、各“冗余”内容的具体作用

  • __mh_execute_header:Mach-O格式的执行头,是macOS加载器识别程序的核心信息块,包含程序架构(ARM64)、入口点地址、内存段布局、权限配置等关键数据。没有它,系统根本不知道如何把你的程序加载到内存执行。
  • __TEXT:Mach-O的代码段,专门存放你的汇编指令,是程序的核心执行部分;ltmp0是汇编器as编译过程中生成的临时符号,用于临时标记地址,属于编译中间产物,链接后可能残留。
  • __unwind_info:ARM64架构的栈回溯信息,用于程序崩溃时生成栈调用链、处理异常(如信号),macOS的系统错误机制依赖该信息生成崩溃报告,是用户态程序的强制要求。
  • /usr/lib/libSystem.B.dylib:动态链接的系统库依赖,你的Hello World大概率调用了libc的write或printf函数,这些函数不在你的程序体内,需要运行时加载系统库提供功能,这个路径就是告诉加载器要关联的库文件。
  • 大量0x00字节:是Mach-O格式的内存对齐要求,ARM64的内存页大小为4KB,程序的段、节都要对齐到页边界,所以需要填充空字节满足对齐规则,确保程序加载到内存后符合硬件的访问规范。

三、为什么NASM输出更精简?

NASM的“精简”取决于你指定的输出格式:如果用nasm -f bin生成纯二进制,确实没有任何格式信息;但如果用nasm -f macho64生成Mach-O目标文件,再链接成可执行程序,同样会包含上述的Mach-O头、段信息等内容。

而as默认生成符合系统标准的目标文件,链接时遵循macOS可执行程序规范,会自动添加必要的格式信息和依赖,所以体积看起来更大。

四、这些内容是否必要?

对macOS的用户态程序来说,核心部分(Mach-O头、代码段、unwind信息、动态链接依赖)是必须的——macOS是多任务操作系统,所有用户程序都要通过系统加载器管理,依赖系统提供的服务(如文件描述符、输出功能),没有这些内容系统无法运行你的程序。

只有裸机程序(如BIOS引导程序、嵌入式固件)才不需要这些,但这类程序无法在macOS用户态运行。

五、精简体积的方法

虽然无法完全去掉所有格式信息,但可以通过以下方式缩小体积:

  1. 直接调用系统调用而非libc函数:跳过libc的动态链接,用ARM64的svc #0指令直接触发系统调用。比如写Hello World时,直接调用write的系统调用号(macOS ARM64下为0x4),这样可以去掉对libSystem.B.dylib的依赖,大幅缩小体积。
  2. 用strip清理符号表:编译链接后执行strip your_program,可以去掉调试符号、临时符号(如ltmp0),能减少几KB的体积。
  3. 手动编写最小Mach-O程序:用汇编直接编写Mach-O的头、代码段,只保留必要的格式信息,跳过不必要的节(如额外调试信息),这种方式可以生成几KB甚至更小的可执行程序。
  4. 用NASM编译Mach-O格式:指定nasm -f macho64,编写汇编时手动控制段定义,避免生成多余的符号和节,相比as可以更灵活地控制输出内容。

内容的提问来源于stack exchange,提问作者axolotlKing0722

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 11:25:30