一个操作系统的设计与实现——第18章 欢迎回来

18.1 引言

我们已经实现了一个运行在保护模式下的操作系统,然而,读者朋友也许不会满足:如今早已是多核CPU,64位操作系统的时代,而我们的操作系统仅仅是单核CPU,32位的。因此,从本章开始,我们将在32位单核操作系统的基础上,将其升级为一个64位多核操作系统。

18.2 准备工作

我们仍然使用bochs虚拟机作为操作系统的运行和调试环境。但其编译命令需要增加一些选项:

  • 对于bochs./configure --prefix=... --enable-x86-64 --enable-smp && make -jN && make install
  • 对于bochsdbg./configure --prefix=... --enable-debugger --enable-x86-64 --enable-smp && make -jN && make install

新增的--enable-x86-64选项用于启用64位模式;--enable-smp选项用于启用多处理器模式。

此外,bochsdbg-rc参数是一个很实用的功能,其可以使bochsdbg在启动时自动执行一串调试命令,建议读者根据需要自行配置这个参数。

18.3 64位寄存器

64位CPU的通用寄存器宽度是64位的,不仅如此,其还新增了8个通用寄存器r8 ~ r15,并拓展了现有寄存器的用法:现在,所有的寄存器都有8、16、32、64位版本。这些寄存器如下表所示:

64位版本 32位版本 16位版本 8位版本
rax eax ax al/ah
rbx ebx bx bl/bh
rcx ecx cx cl/ch
rdx edx dx dl/dh
rsi esi si sil
rdi edi di dil
rbp ebp bp bpl
rsp esp sp spl
r8 r8d r8w r8b
r9 r9d r9w r9b
r10 r10d r10w r10b
r11 r11d r11w r11b
r12 r12d r12w r12b
r13 r13d r13w r13b
r14 r14d r14w r14b
r15 r15d r15w r15b

64位CPU有一个特殊设定:当向一个32位寄存器传送时,其高32位将被自动清零。也就是说,不需要也不存在这样的指令:movzx 64位寄存器, 32位寄存器;然而,movsx 64位寄存器, 32位寄存器与此设定不矛盾,故仍然存在。

标志寄存器也拓展至64位,被称为rflags。然而,由于其低32位都还没用完,因此拓展出的高32位均为保留位。

指令指针寄存器也拓展至64位,被称为rip

18.4 64位立即数

由于机器语言层面的限制,CPU对64位立即数的支持非常差,以至于只需要以下规则就能描述:

  • mov 64位寄存器, 64位立即数唯一支持64位立即数的指令
  • 其他指令如果强行使用64位立即数,也只会取其低32位

也就是说,很多非常依赖立即数的指令,如内存访问,加减法,位运算等,都不能使用64位立即数,而是需要先使用mov指令进行周转。

18.5 RIP相对寻址

64位CPU新增了一种内存访问模式,被称为RIP相对寻址。具体来说:在nasm语法中,[标号][abs 标号]表示的是普通的内存寻址模式,此时,标号的值就是内存地址;[rel 标号]表示的是新增的RIP相对寻址,此时,该指令会被编译器转换为[rip + 标号相对于rip的偏移量]。这样做的好处在于:64位模式下,直接使用[标号]是有风险的,因为标号很有可能是一个超过32位的立即数,不过,由于标号往往离rip比较近,相对偏移量较小,故不会超过32位的限制。

在nasm中,可以通过声明[default rel]将所有的[标号]都视为[rel 标号]

需要注意的是,RIP相对寻址只适用于[标号]这种形式,其他形式,如:[寄存器 + 标号][64位立即数]等,都是不适用于RIP相对寻址的,这是因为这些指令都无法确定地址与rip的相对偏移量。

本章讨论了64位CPU的寄存器和内存寻址,64位CPU的其他特点将在后续章节中讨论。从下一章开始,我们将正式开始实现64位操作系统。

posted @ 2024-08-31 10:11  樱雨楼  阅读(13)  评论(0编辑  收藏  举报