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

AS汇编器undefined label错误:GDT初始化相关符号未定义

OS开发GDT初始化链接错误排查与解决

问题背景

在OS开发过程中,初始化GDT时遇到链接错误,相关代码、编译命令及错误信息如下:

相关代码

boot.s 代码

.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 .multiboot
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
 
.section .bss
.align 16
stack_bottom:
.skip 16384 # 16 KiB
stack_top:
 


.section .text
.global _start

.type _start, @function
_start:

    mov $stack_top, %esp
 

    # setup GDT
    cli
    xor %ax, %ax
    mov %ds, %ax
    lgdt gdt_desc
    sti


    call kernel_main
 

    cli
1:  hlt
    jmp 1b
 
.size _start, . - _start

gdt.s 代码

.global gdt
.global gdt_null
.global gdt_code
.global gdt_data
.global gdt_end
.global gtd_desc
gdt:

gdt_null:
    .8byte 0

gdt_code:
    .2byte 0xFFFF
    .2byte 0x0000
    .byte 0
    .byte 0b10011010
    .byte 0b11001111
    .byte 0
gdt_data:
    .2byte 0xFFFF
    .2byte 0
    .byte 0
    .byte 0b10010010
    .byte 0b11001111
    .byte 0
gtd_end:

gtd_desc:
    .2byte gdt_end - gdt
    .2byte gdt

链接脚本 linker.ld

ENTRY(_start)

SECTIONS
{
    . = 1M;
    .text BLOCK(4K) : ALIGN(4K)
    {
        *(.multiboot)
        *(.text)
    }
 
    /* Read-only data. */
    .rodata BLOCK(4K) : ALIGN(4K)
    {
        *(.rodata)
    }
 
    /* Read-write data (initialized) */
    .data BLOCK(4K) : ALIGN(4K)
    {
        *(.data)
    }
 
    /* Read-write data (uninitialized) and stack */
    .bss BLOCK(4K) : ALIGN(4K)
    {
        *(COMMON)
        *(.bss)
    }
 
}

编译链接命令

as --32 boot.s -o boot.o
as --32 gdt.s -o gdt.o
g++ -m32 -T linker.ld -o myos.bin -ffreestanding -O2 -nostdlib boot.o kernel.o gdt.o -lgcc

链接错误信息

/usr/bin/ld: boot.o: in function `_start':
(.text+0xf): undefined reference to `gdt_desc'
/usr/bin/ld: gdt.o: in function `gtd_end':
(.text+0x18): undefined reference to `gdt_end'
(.text+0x18): relocation truncated to fit: R_386_PC8 against undefined symbol `gdt_end'
(.text+0x19): relocation truncated to fit: R_386_16 against `.text'

错误原因与解决方法

1. 符号拼写错误

  • boot.s中引用的是gdt_desc,但gdt.s里定义的全局符号是gtd_desc(拼写少了一个t),导致未定义引用。
  • gdt.s中计算GDT长度时用了gdt_end,但实际定义的结束标签是gtd_end,同样拼写错误。

修正方案:
修改gdt.s中的符号名,保持一致:

.global gdt
.global gdt_null
.global gdt_code
.global gdt_data
.global gdt_end
.global gdt_desc  // 修正为gdt_desc
gdt:

// ... 中间GDT项代码不变 ...

gdt_end:  // 修正为gdt_end

gdt_desc:  // 修正为gdt_desc
    .2byte gdt_end - gdt
    .4byte gdt  // 此处同时修正基地址长度

2. GDT描述符基地址长度错误

原gdt.s中用.2byte gdt存储GDT基地址,但32位模式下GDT描述符的基地址是32位,必须用4字节存储,否则会截断地址,引发 relocation 错误。

修正方案:
将.2byte gdt改为.4byte gdt,确保基地址完整。

3. (可选)将GDT放入只读数据段

当前GDT默认放在.text段,可将其移至.rodata段(只读数据段),更符合数据属性:
在gdt.s开头添加.section .rodata:

.section .rodata
.global gdt
.global gdt_null
.global gdt_code
.global gdt_data
.global gdt_end
.global gdt_desc
gdt:

// ... 后续代码不变 ...

修正后重新编译链接即可解决所有错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 04:18:17