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

16位实模式C内核全局变量失效问题求助

16位实模式C内核全局变量失效问题求助

我正在尝试用C语言编写一个16位实模式的操作系统,目前使用的是Open Watcom C编译器和链接器。

现在遇到了一个棘手的问题:当我在kmain函数里用局部变量定义VGA显存指针时,代码能正常在QEMU中打印消息,可一旦把这个指针改成全局变量,屏幕上就再也出不了内容了。

先贴出能正常工作的代码:

#define VGA_MEM  0xB8000000UL
#define WHITE_ON_BLACK 0x07

void write_string(unsigned char far* vga, const char* msg)
{
    int i = 0;

    while (msg[i]) {
        vga[i * 2] = msg[i];
        vga[i * 2 + 1] = WHITE_ON_BLACK;
        i++;
    }
}

void kmain()
{
    unsigned char far* vga = (unsigned char far *)VGA_MEM;
    const char* msg = "Hello from Watcom C kernel!";
    write_string(vga, msg);
    for (;;);
}

下面说明我的OS结构:

  • boot.asm负责将第2扇区(CHS寻址)加载到0x1000:0x0000,然后跳转到该位置
  • 这个扇区里的kernel.bin是由entry.obj和kernel.o链接而成,其中entry.asm作为入口文件放在最前面,代码如下:
BITS 16

GLOBAL _start
EXTERN kmain_

SEGMENT CONST CLASS=DATA
SEGMENT CONST2 CLASS=DATA
SEGMENT _DATA CLASS=DATA
SEGMENT _BSS CLASS=BSS
GROUP DGROUP CONST CONST2 _DATA _BSS

SEGMENT TEXT CLASS=CODE

_start:
    CLI
    PUSH    cs
    POP     ax
    MOV     ds, ax
    MOV     es, ax
    XOR     ax, ax
    MOV     ss, ax
    MOV     sp, 0x9FFF
    STI

    JMP     kmain_

我查了相关资料,知道DS寄存器应该指向DGROUP的起始位置,这里是kernel.bin的段映射信息:

Segment                Class          Group          Address         Size

=======                =====          =====          =======         ====

TEXT                    CODE           AUTO           00010000        00000012
\_TEXT                  CODE           AUTO           00010012        00000042
CONST                   DATA           DGROUP         00010054        0000002d
CONST2                  DATA           DGROUP         00010082        00000002
\_DATA                  DATA           DGROUP         00010084        00000012
\_BSS                   BSS            DGROUP         00010096        00000002

其中:

  • TEXT段对应entry.asm的内容
  • _TEXT段对应kernel.c的内容
  • 全局的vga指针存放在_DATA段

现在的核心问题是:我不知道该如何正确让DS指向DGROUP。我试过在运行时计算DGROUP的地址,但执行MOV ds, 计算出的DGROUP地址后,实际的DGROUP地址似乎又发生了变化。

我还尝试过把CODE类的段也加入DGROUP,这样全局变量确实能正常工作了,但直觉告诉我这绝对不是正确的解决方案。另外我也翻了Open Watcom链接器的官方手册,但没找到能解决这个问题的有效信息。

最后附上我的linker.lnk文件内容:

NAME kernel.bin
FORMAT RAW BIN

OPTION  QUIET,
        NODEFAULTLIBS,
        START=_start,
        VERBOSE,
        OFFSET=0x10000,
        STACK=0x200,
        MAP

FILE entry.obj
FILE kernel.o

ORDER
    CLNAME CODE
    CLNAME DATA
    CLNAME BSS

备注:内容来源于stack exchange,提问作者Ld120

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 18:38:08