<?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>E820 on 大飞的博客</title>
    <link>https://www.dafei.me/tags/e820/</link>
    <description>Recent content in E820 on 大飞的博客</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Wed, 06 May 2026 06:00:00 +0000</lastBuildDate>
    <atom:link href="https://www.dafei.me/tags/e820/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>从零写OS（六）：内存管理，知道自己有多少地可种</title>
      <link>https://www.dafei.me/posts/os-06-memory/</link>
      <pubDate>Wed, 06 May 2026 06:00:00 +0000</pubDate>
      <guid>https://www.dafei.me/posts/os-06-memory/</guid>
      <description>&lt;p&gt;内核跑起来之后，第一个绕不开的问题就是内存。&lt;/p&gt;
&lt;p&gt;你不知道这台机器有多少内存，哪些地址段可以用，哪些是硬件保留的。如果随便往一个地址写数据，轻则数据损坏，重则触发异常直接重启。&lt;/p&gt;
&lt;p&gt;这一章解决一件事：&lt;strong&gt;让内核知道内存的全貌，然后有序地分配和回收物理页&lt;/strong&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;先问-bios你有多少内存&#34;&gt;先问 BIOS：你有多少内存？&lt;/h2&gt;
&lt;p&gt;我们用 &lt;strong&gt;E820&lt;/strong&gt;（BIOS INT 0x15 AX=E820h，一种标准接口，用来查询物理内存的分布和类型）来探测内存。&lt;/p&gt;
&lt;p&gt;这事必须在实模式下做——切换到长模式之后就再也访问不到 BIOS 服务了。所以探测代码放在 &lt;code&gt;boot.asm&lt;/code&gt; 里，在进入长模式之前完成。&lt;/p&gt;
&lt;p&gt;每次调用 INT 0x15，BIOS 填一条 24 字节的记录：&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;base    (8字节) — 这段内存的起始物理地址
length  (8字节) — 这段内存的长度（字节）
type    (4字节) — 类型：1=可用，2=保留，其它=别动
ACPI    (4字节) — 扩展属性，一般忽略
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;循环调用直到 EBX 变成 0，表示枚举完毕。所有记录写入固定地址 &lt;code&gt;0x8000&lt;/code&gt;，第一个 4 字节存条目数量。&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;mov&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;di&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;MMAP_ADDR&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;   &lt;span style=&#34;color:#75715e&#34;&gt;; 从 0x8004 开始存条目
&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;xor&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ebx&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;ebx&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;xor&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bp&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;bp&lt;/span&gt;              &lt;span style=&#34;color:#75715e&#34;&gt;; bp 记条目数量
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.e820_loop:
&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;eax&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0xE820&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;ecx&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;24&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;edx&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0x534D4150&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;; &amp;#34;SMAP&amp;#34; 魔数，BIOS 验证用
&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;int&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0x15&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;jc&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;.e820_done&lt;/span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;; CF=1 表示出错或结束
&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;inc&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bp&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;add&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;di&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;24&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;test&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;ebx&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;ebx&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;jz&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;.e820_done&lt;/span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;; ebx=0 表示最后一条
&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;jmp&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;.e820_loop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.e820_done:
&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;dword&lt;/span&gt; [&lt;span style=&#34;color:#66d9ef&#34;&gt;MMAP_ADDR&lt;/span&gt;], &lt;span style=&#34;color:#66d9ef&#34;&gt;ebp&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;; 把条目数量写到 0x8000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;QEMU 上跑出来的内存地图一般长这样：&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
