Jen*_*ger 2 x86 assembly osdev multiboot grub2
我尝试将以下代码用于 Multiboot2 兼容内核的标头,但是当我multiboot2在 grub 中尝试该命令时,它给出了以下错误消息:
错误:不支持的标签:0xc
我的 Multiboot2 标头定义为:
section .multiboot align=4096
mbhead: dd 0xe85250d6
dd 0
dd 76
dd 0 - 76 - 0xe85250d6 ; TODO the linker and assembler get angry if we calculate this with symbols, we need to do this by hand
dw 1 ; multiboot information request
dw 0
dd 20
dd 1
dd 2
dd 6
dw 4 ; console flags
dw 0
dd 12
dd 0x3
dw 5 ; framebuffer settings
dw 1
dd 12
dd 80
dd 25
dd 0
dw 0 ; last tag
dw 0
dd 8
Run Code Online (Sandbox Code Playgroud)
我的项目存储库提供了完整的源代码。我用make test_longmode.iso. 我用 QEMU 测试。
导致标签错误的问题是什么,我该如何解决?
GRUB 错误:
错误:不支持的标签:0xc
是因为您没有按照Multiboot2 规范对每个标签进行 8 字节对齐:
3.1.3 通用标签结构
标签构成了一个结构缓冲区,在必要时相互填充,以便每个标签从 8 字节对齐的地址开始。标签以“0”类型和“8”大小的标签结束。每个结构都有以下格式
为了轻松解决这个问题,您可以align 8在每个标签之前使用,您可以让汇编程序处理对齐。这种对齐不会计算到标签的长度中。
您可以更好地计算校验和,以免通过让 NASM 使用截断来引起警告。这一行:
dd 0 - 76 - 0xe85250d6
Run Code Online (Sandbox Code Playgroud)
可以更好地表达为:
dd 0x100000000 - 76 - 0xe85250d6
Run Code Online (Sandbox Code Playgroud)
我认为关于这段代码片段的第一件事是它是多么不可读。引起我注意的是这条评论:
TODO 如果我们用符号计算它,链接器和汇编器会生气,我们需要手动完成
您似乎手动计算了值,因为您在尝试以其他方式进行计算时遇到了问题。在这里有帮助的 NASM 指令是EQU 指令:
3.2.4 EQU:定义常量
EQU 将符号定义为给定的常量值:当使用 EQU 时,源代码行必须包含一个标签。EQU 的作用是将给定的标签名称定义为其(仅)操作数的值。这个定义是绝对的,以后不能改变。所以,例如,
Run Code Online (Sandbox Code Playgroud)message db 'hello, world' msglen equ $-message将 msglen 定义为常量 12。 msglen 以后可能不会重新定义。这也不是预处理器定义:msglen 的值被评估一次,在定义点使用 $ 的值(有关 $ 的解释,请参阅第 3.5 节),而不是在任何被引用的地方评估并使用$ 在参考点。
通过使用 EQU,我们可以使代码更具可读性。
其次,您可以在每个标签的开头和结尾添加标签,然后让汇编程序为您计算每个标签的长度。长度是每个标签的结束标签和开始标签之间的差值。
具有上述建议更改的 NASM 汇编代码可能如下所示:
MB2_ARCH EQU 0 ; 0 = x86/x86-64
MB2_LEN EQU (mbend-mbhead)
MB2_MAGIC EQU 0xe85250d6
section .multiboot align=4096
mbhead:
dd MB2_MAGIC ; Multiboot2 magic number
dd MB2_ARCH ; Architecture
dd MB2_LEN ; Multiboot header length
dd 0x100000000 - MB2_LEN - MB2_ARCH - MB2_MAGIC
; Checksum
mb2_tag_info_start:
dw 1 ; multiboot information request
dw 0
dd mb2_tag_info_end - mb2_tag_info_start
dd 1
dd 2
dd 6
mb2_tag_info_end:
align 8
mb2_tag_console_start:
dw 4 ; console flags
dw 0
dd mb2_tag_console_end - mb2_tag_console_start
dd 0x3
mb2_tag_console_end:
align 8
mb2_tag_fb_start:
dw 5 ; framebuffer settings
dw 1
dd mb2_tag_fb_end - mb2_tag_fb_start
dd 80
dd 25
dd 0
mb2_tag_fb_end:
align 8
mb2_tag_end_start:
dw 0 ; last tag
dw 0
dd mb2_tag_end_end - mb2_tag_end_start
mb2_tag_end_end:
mbend:
Run Code Online (Sandbox Code Playgroud)
这可以进一步改进,但即使这样看起来也比原始代码片段更具可读性和自我记录性。如果您更改标签或标题的大小,则会为您计算所有长度。如果大小发生变化,该align 8指令将为您计算正确的对齐方式。这使得代码更易于维护。
| 归档时间: |
|
| 查看次数: |
433 次 |
| 最近记录: |