Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly GNU GRUB给出了;错误:不支持的标记:0xc";用于多引导2_Assembly_X86_Osdev_Grub2_Multiboot - Fatal编程技术网

Assembly GNU GRUB给出了;错误:不支持的标记:0xc";用于多引导2

Assembly GNU GRUB给出了;错误:不支持的标记:0xc";用于多引导2,assembly,x86,osdev,grub2,multiboot,Assembly,X86,Osdev,Grub2,Multiboot,我尝试使用以下代码作为与Multiboot2兼容的内核的头,但是当我在grub中尝试使用Multiboot2命令时,它给出了以下错误消息: 错误:不支持的标记:0xc 我的Multiboot2标头定义为: section .multiboot align=4096 mbhead: dd 0xe85250d6 dd 0 dd 76 dd 0 - 76 - 0xe85250d6 ; TODO the linker an

我尝试使用以下代码作为与Multiboot2兼容的内核的头,但是当我在grub中尝试使用
Multiboot2
命令时,它给出了以下错误消息:

错误:不支持的标记: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
My提供了完整的源代码。我用
make test\u longmode.ISO
生成一个ISO。我使用QEMU进行测试

导致标记错误的问题是什么?如何修复它?

主要问题 GRUB错误:

错误:不支持的标记:0xc

这是因为您没有按照以下方式对每个标记进行8字节对齐:

3.1.3一般标签结构

标签构成一个结构缓冲区,在必要时相互填充,以便每个标签从8字节对齐的地址开始。标记由类型为“0”且大小为“8”的标记终止。每个结构都有以下格式

要轻松解决此问题,可以在每个标记之前使用
align 8
,并且可以让汇编程序处理对齐。此对齐不会计算到标记的长度中

通过让NASM使用截断,可以更好地计算校验和,以免引起警告。这一行:

dd 0 - 76 - 0xe85250d6
可以更好地表述为:

dd 0x100000000 - 76 - 0xe85250d6

代码可读性 我认为关于这个代码片段的第一件事就是它的可读性。引起我注意的是这一评论:

为了让链接器和汇编程序生气,如果我们用符号计算,我们需要手工完成

似乎您可能手工计算了值,因为您在尝试以其他方式进行计算时遇到了问题。有助于此的NASM指令是:

3.2.4等式:定义常数

EQU将符号定义为给定的常量值:使用EQU时,源行必须包含标签。EQU的作用是将给定的标签名定义为其(唯一)操作数的值。此定义是绝对的,以后不能更改。那么比如说,

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:

这可以进一步改进,但即使这样,也比原始代码片段更具可读性和自文档性。如果更改标记或标题的大小,将为您计算所有长度。如果尺寸改变,
align 8
指令将为您计算正确的对齐方式。这使代码更易于维护。

您应该更好地注释代码。无论如何,我猜您违反了“必要时进行填充,以便每个标记从8字节对齐的地址开始”。20号和12号不是8号的倍数,所以这已经很可疑了。可能就是这样。我看看这是否有帮助。链接应该被修复。这是。这与您的示例类似,不过我使用了NASM的本地标签对标记中的各个项目进行注释,并在相同的重复代码段中共享标记大小计算,即
.size:dd.end-.
行。