You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GNU i386汇编器GDT代码转换报错,求排查解决

GAS汇编转换GDT代码时的编译错误修复

背景

我正在学习OSDev的GDT设置教程,将NASM语法的示例代码手动转换为GAS语法(工具intel2gas无法处理部分代码),使用GNU-i386交叉编译器。以下是我的boot.S代码:

# 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

编译错误

编译时出现以下错误:

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

错误原因

错误中的GDT39是因为代码中用双引号''GDT''包裹符号名导致的:GAS汇编中不需要用引号引用符号,双引号会被解析为字符串,而39是单引号(ASCII 0x27)的十进制值,最终造成汇编器解析混乱。

另外原代码中movl [gdtr + 2], %eax逻辑错误,这是读取gdtr+2地址的值到%eax,但实际需求是把计算出的GDT物理地址写入gdtr的长字部分(即gdtr+2的位置)。

修复后的setGdt代码

修改两处问题:去掉符号名的双引号,修正寄存器和内存的读写方向:

gdtr:   .word 0
        .long 0

setGdt:
    xorl %eax,%eax
    movw %ds,%ax
    shll $4,%eax
    addl $GDT, %eax          # 移除双引号,直接引用符号
    movl %eax, [gdtr + 2]    # 将GDT物理地址写入gdtr的长字部分
    movl $GDT_end, %eax      # 移除双引号
    subl $GDT, %eax          # 移除双引号
    movw %ax, gdtr
    lgdt [gdtr]
    ret

额外注意事项

  • 确保你已经在代码中定义了GDT和GDT_end符号(比如在.rodata段中定义GDT表结构),否则会出现未定义符号的编译错误;
  • GAS中引用符号、标签时直接写名称即可,不需要添加引号或其他包裹符。

内容的提问来源于stack exchange,提问作者Wutpups

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 09:27:39