【问题标题】:Syntax of x86 assembly codex86 汇编代码的语法
【发布时间】:2023-10-18 07:49:01
【问题描述】:

我正在尝试了解操作系统的基础知识,并在 OCW(名为 6.828)中找到了有关它的课程。在课程的labs中找到了bootloader的代码,试过了但是没看懂下面这段代码:

# Enable A20:

#   For backwards compatibility with the earliest PCs, physical

#   address line 20 is tied low, so that addresses higher than

#   1MB wrap around to zero by default.  This code undoes this.

seta20.1:
inb     $0x64,%al               # Wait for not busy
testb   $0x2,%al
jnz     seta20.1

movb    $0xd1,%al               # 0xd1 -> port 0x64
outb    %al,$0x64

seta20.2:
inb     $0x64,%al               # Wait for not busy
testb   $0x2,%al
jnz     seta20.2

movb    $0xdf,%al               # 0xdf -> port 0x60
outb    %al,$0x60

我们如何检查端口 0x64 是否忙,以及为什么要使用此端口来启用 A20 位?进一步使芯片运行到 GDT 的 32 位模式配置如下:

# Switch from real to protected mode, using a bootstrap GDT

# and segment translation that makes virtual addresses 

# identical to their physical addresses, so that the 

# effective memory map does not change during the switch.

lgdt    gdtdesc
# Bootstrap GDT
.p2align 2                                # force 4 byte alignment
gdt:
SEG_NULL                # null seg
SEG(STA_X|STA_R, 0x0, 0xffffffff)   # code seg
SEG(STA_W, 0x0, 0xffffffff)         # data seg

gdtdesc:
.word   0x17                            # sizeof(gdt) - 1
.long   gdt                             # address gdt

上面的代码是做什么的?以“.”开头的行是什么意思?此外,汇编代码似乎有两种格式 .S 和 .asm 两者有什么区别?

【问题讨论】:

    标签: assembly x86 operating-system


    【解决方案1】:

    我们如何检查端口 0x64 是否繁忙?

    就在那儿。如果设置了bit #1(值2),则端口忙。

    为什么使用这个端口来启用 A20 位

    历史原因。将此功能连接到键盘控制器很容易。就像 cpu 重置线一样。

    上面的代码做了什么?

    使用三个描述符设置 GDT:nullcodedata。我不会在这里解释 GDT 是什么以及保护模式分段是如何工作的。我希望它在教程中有所涉及,否则请咨询osdev.org

    以“.”开头的行是什么意思?

    这些是汇编器的指令,它们指示它做事。例如.word 指示它发出具有给定值的单词。有关详细信息,请参阅汇编器手册。

    汇编代码似乎有两种格式 .S 和 .asm

    汇编文件有 2 个(或者更确切地说是 3 个,分别计算 .s.S)通用扩展名。 .s 版本通常用于 gnu 工具链,而.asm 用于其他版本。有两种以上的格式,每个汇编程序几乎都有一种。这些只是文件的常用扩展名,它们并没有真正定义内容。

    PS:看起来你是汇编的初学者,这很好,但也许你不应该在积累一些经验之前立即开始使用低级操作系统的东西。

    【讨论】:

    • 在设置 GDT 时,命令 SEG_NULL, SEG(STA_X, 0x0, 0xffffffff)....是什么意思? gdtdesc 中的 .word 和 .long 指令有什么作用?
    • SEG_NULLSEG 是前面定义的宏,未在您的问题中显示。 GDT 是一个包含描述段的数据的表。该数据是使用宏设置的。 gdtdesc 反过来描述 GDT,正如评论所说,大小和位置。 LGDT 指令需要它。
    【解决方案2】:

    我们如何检查端口 0x64 是否繁忙以及为什么这个端口 用于启用A20位?

    您从该端口检查第三位。更详细:

    inb     $0x64,%al ; read byte from port 0x64
    testb   $0x2,%al  ; check 3rd bit
    jnz     seta20.1  ; if not 0, check again
    

    为什么是这个端口而不是另一个端口只是一个决定问题。它可以是任何数字。这实际上并不相关。更多详情可以查看this

    上面的代码做了什么?

    准备从实模式切换到protected mode

    以“.”开头的行是什么意思?

    这些是汇编指令。它们不生成代码,但可以用于其他事情。例如.p2align 用于将数据/代码与某些字节倍数对齐,.word 声明一个字(在本例中为值 0x0017)等...

    汇编代码似乎有两种格式 .S 和 .asm 什么 两者有什么区别?

    它们只是扩展名(不要与文件格式混淆)。他们实际上没有任何意义。代码文件是文本文件。

    【讨论】:

      最近更新 更多