<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>内存映射 on 大飞的博客</title>
    <link>https://www.dafei.me/tags/%E5%86%85%E5%AD%98%E6%98%A0%E5%B0%84/</link>
    <description>Recent content in 内存映射 on 大飞的博客</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Wed, 06 May 2026 16:00:00 +0000</lastBuildDate>
    <atom:link href="https://www.dafei.me/tags/%E5%86%85%E5%AD%98%E6%98%A0%E5%B0%84/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>从零写OS（十六）：ELF 加载器，运行第一个用户程序</title>
      <link>https://www.dafei.me/posts/os-16-elf/</link>
      <pubDate>Wed, 06 May 2026 16:00:00 +0000</pubDate>
      <guid>https://www.dafei.me/posts/os-16-elf/</guid>
      <description>&lt;p&gt;这一章做完，我们的系统就有了完整的用户程序执行链路：写一个独立的程序，编译成 ELF，放到磁盘上，Shell 里输入 &lt;code&gt;run hello.elf&lt;/code&gt;，内核加载并执行它。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;elf-是什么&#34;&gt;ELF 是什么&lt;/h2&gt;
&lt;p&gt;ELF（Executable and Linkable Format）是 Linux 可执行文件的格式。你编译出来的每个程序、&lt;code&gt;/bin/ls&lt;/code&gt;、&lt;code&gt;/usr/bin/python&lt;/code&gt; 都是 ELF 文件。&lt;/p&gt;
&lt;p&gt;结构很简单：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ELF Header        → 魔数、架构、入口地址
Program Headers   → 每个段加载到内存哪里、从文件哪里读
.text             → 代码
.data             → 数据
.bss              → 未初始化数据（文件里不占空间，加载时清零）
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;加载一个 ELF，本质上就是：&lt;strong&gt;按 Program Header 的指示，把文件里的数据复制到内存里，然后跳到入口地址&lt;/strong&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;先写用户程序&#34;&gt;先写用户程序&lt;/h2&gt;
&lt;p&gt;用户程序不能调内核函数，只能通过 &lt;code&gt;syscall&lt;/code&gt; 和内核通信：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;BITS&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;section&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;.text&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;global&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;_start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;_start:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;mov&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;rax&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;              &lt;span style=&#34;color:#75715e&#34;&gt;; syscall 1 = print
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;lea&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;rdi&lt;/span&gt;, [&lt;span style=&#34;color:#66d9ef&#34;&gt;rel&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;msg&lt;/span&gt;]      &lt;span style=&#34;color:#75715e&#34;&gt;; RIP 相对寻址
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;syscall&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;mov&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;rax&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;              &lt;span style=&#34;color:#75715e&#34;&gt;; syscall 2 = exit
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;syscall&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;section&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;.data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;msg: &lt;span style=&#34;color:#a6e22e&#34;&gt;db&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;Hello&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ELF&lt;/span&gt;!&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;13&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;链接时指定加载地址 &lt;code&gt;0x400000&lt;/code&gt;（避开内核占用的低地址区域）：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-ld&#34; data-lang=&#34;ld&#34;&gt;ENTRY(_start)
SECTIONS {
    . = 0x400000;
    .text : { *(.text) }
    .data : { *(.data) }
}
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id=&#34;elf-加载器&#34;&gt;ELF 加载器&lt;/h2&gt;
&lt;p&gt;加载流程：&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
