leal rva(pgtable)(%ebx), %edi rva和pgtable是内核解压启动代码里用于计算内存地址的关键元素pgtable是一个符号Symbol代表着页表数据在内存中的起始地址。它相当于一个标签标记了为内核启动而临时创建的页表数据存放的位置。rva()是一个汇编宏Macro用于计算相对虚拟地址Relative Virtual Address。它的作用是在内核代码被加载到内存后根据当前实际的运行地址计算出像pgtable这样符号的实际内存地址。 为什么需要rva()在head_64.S这个阶段内核或者说解压程序刚刚被引导程序加载到内存中但它还没有被解压和重定位到最终的位置。因此代码中符号如pgtable的编译时地址链接地址和它的运行时地址是不一致的。rva(pgtable)(%ebx)这行代码就是为了解决这个问题。它通过rva(pgtable)计算出pgtable相对于某个基准点的偏移量然后加上寄存器%ebx中保存的当前代码运行时的基地址从而得到pgtable在内存中的真实物理地址。它在页表初始化中的作用在 Linux 内核的启动早期head_64.S中这段代码通常用于建立临时的页表为开启 CPU 的分页模式做准备。整个过程是定位页表空间使用leal rva(pgtable)(%ebx), %edi将页表的起始地址运行时的真实地址存入edi寄存器。edi在这里作为目标地址指针。构建页表随后代码会基于edi指向的地址向其中写入页目录项PDE、页表项PTE等数据一步步构建起从虚拟地址到物理地址的映射关系。激活分页页表构建完成后会将页表的基地址即pgtable的真实地址加载进cr3控制寄存器从而正式启用分页机制。rva()这种汇编技巧是内核在重定位之前能够正确访问自身数据的关键确保了即便代码不在链接时指定的地址运行也能准确地找到像页表这样的关键数据结构。#define rva(X) ((X) - startup_32)它的作用这个宏的作用是计算一个符号比如pgtable与startup_32入口点之间的偏移量。背景在head_64.S这个阶段代码被加载到内存后其运行时的实际地址和编译时预设的地址可能不一致。rva宏正是用来获取这种相对位移。在leal中的用法你问的这行代码leal rva(pgtable)(%ebx), %edi它的执行过程是rva(pgtable)先计算出pgtable符号相对于startup_32的偏移量。此时寄存器%ebx中保存着当前代码段的运行基址。将偏移量加上运行基址(%ebx)就得到了pgtable在内存中的真实物理地址。最后将结果存入%edi寄存器作为指针用于后续的页表构建。