我尝试遵循wiki.osdev.org中关于GDT设置的教程。我试图将示例代码从NASM转换为GAS语法,但工具intel2gas无法转换一些行,然后我自己尝试了。我不得不说,我对汇编程序了解不多。这是我启动时的代码。S和我正在使用GNU-i386交叉编译器:
# Declare constants for the multiboot header.
.set ALIGN, 1<<0 # align loaded modules on page boundaries
.set MEMINFO, 1<<1 # provide memory map
.set FLAGS, ALIGN | MEMINFO # this is the Multiboot 'flag' field
.set MAGIC, 0x1BADB002 # 'magic number' lets bootloader find the header
.set CHECKSUM, -(MAGIC + FLAGS) # checksum of above, to prove we are multiboot
.section .rodata
# Declare a header as in the Multiboot Standard.
.section .multiboot
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
# Reserve a stack for the initial thread.
.section .bss
.align 16
stack_bottom:
.skip 16384 # 16 KiB
stack_top:
# The kernel entry point.
.section .text
.global _start
.type _start, @function
_start:
movl $stack_top, %esp
# Call the global constructors.
call _init
# Transfer control to the main kernel.
call kernel_main
# Hang if kernel_main unexpectedly returns.
cli
1: hlt
jmp 1b
.size _start, . - _start
gdtr: .word 0
.long 0
setGdt:
xorl %eax,%eax
movw %ds,%ax
shll $4,%eax
addl $''GDT'', %eax
movl [gdtr + 2], %eax
movl $''GDT_end'', %eax
subl $''GDT'', %eax
movw %ax, gdtr
lgdt [gdtr]
ret
这也是OSDev.org上Meaty Skeleton文章中描述的几乎相同的文件。
我的错误是:
arch/i386/boot.S: Assembler messages:
arch/i386/boot.S:51: Error: junk `GDT39' after expression
arch/i386/boot.S:53: Error: junk `GDT_end39' after expression
arch/i386/boot.S:54: Error: junk `GDT39' after expression
我真的无法解释这些是什么意思。如果您需要任何进一步的信息,请询问。
谢谢你的帮助!
$''GDT''
和类似表达式中的单引号不是有效的GAS语法。不要这样做,只需使用mov $GDT_end, %eax
/sub $GDT, %eax
即可。
或者更好的是,在组装时用mov $GDT_end - GDT, %eax
计算这个常数
GAS可能会被这些窒息,或者因为它以'
开头,所以将整个事情视为一个字符文字。但是GAS在解析'
之后有多个字符的字符文本时却一团糟。
我认为它的解析代码非常简单和粗糙,
因为mov $'a, %eax
(无结束引号(与mov $'a', %eax
组装相同
mov $'abcd', %eax
产生错误:
foo.s:1: Error: backward ref to unknown label "97:"
foo.s:1: Error: junk `cd44%eax' after expression
foo.s:1: Error: number of operands mismatch for `mov'
CCD_ 10将是对标签CCD_ 11(前一行上的最新实例(的向后引用。'a'
的ASCII代码是97
,所以不知何故,它的ab
部分说服GAS将其视为$97b
,忘记了单引号。CCD_ 16是CCD_ 17的ASCII码。
当GAS需要一个整数常量表达式(如在$
之后作为立即数(的上下文中有多个非'
字符作为单引号时,您的错误就是GAS产生的那种无意义的错误。
39
(十进制(是'
单引号的ASCII代码
像NASM这样的更好的汇编程序允许您执行mov eax, 'abcd'
以获得EAX=0x64636261,并准备好存储到内存中以按源顺序获得这些ASCII字节。但GAS并没有这么做,它的解析器甚至没有考虑任何人会尝试的可能性。