Operating system C内核可以';t打印字符串

Operating system C内核可以';t打印字符串,operating-system,kernel,osdev,Operating System,Kernel,Osdev,我写了一个内核来打印hello world。但它不起作用, hello world未打印。 组装打印效果良好 我使用GCC和NASM进行交叉编译和组装 这是我的引导程序,第二阶段代码和C代码 [ORG 0x00] [BITS 16] section .text JMP 0x07C0:START ; START: mov ax, cs mov ds, ax mov es, ax mov ax, 0x0000 mov ss, ax mov

我写了一个内核来打印hello world。但它不起作用, hello world未打印。 组装打印效果良好

我使用GCC和NASM进行交叉编译和组装

这是我的引导程序,第二阶段代码和C代码

[ORG 0x00]
 [BITS 16]

section .text

JMP 0x07C0:START ; 

START:
    mov ax, cs
    mov ds, ax
    mov es, ax

    mov ax, 0x0000
    mov ss, ax
    mov ax, 0xffff
    mov sp, ax
    mov bp, ax

    mov si, 0xB800
    mov es, si
    mov bx, 0x0000
    mov cx, 80*25*2

CLEAR:          ;Clear screen
    mov byte[es:bx], 0x00
    inc bx
    loop CLEAR

READ:               ;Read disk
    mov si, 0x1000
    mov es, si
    mov bx, 0x0000  ; ES:BX, 0x1000:0000
    mov ah, 0x02

    mov al, 2
    mov ch, 0
    mov cl, 2
    mov dh, 0
    mov dl, 0
    int 0x13
    jnc A20_ENABLE  ; No Error -> jump to A20_ENABLE

READERROR:          ;If failed to read disk, 
    jmp $

A20_ENABLE:         ;Enable A20 GATE with BIOS  
    mov ax, 0x2401
    int 0x15
    jnc ENTRY

A20_FAIL:           ;If BIOS Interrupt is not working, use Control Port.
    mov al, 2   ;
    out 0x92, al

ENTRY:              ;Entry Point
    cli             
    lgdt [GDTR]     
    mov eax, cr0
    or eax, 1
    mov cr0, eax

    jmp $+2                         ; for pipeline 
    nop
    nop

    jmp dword 0x08:0x10000           ; jump to second stage

GDTR:                                ; GDT
    dw GDTEND - GDT - 1         
    dd GDT+0x7C00

GDT:
    NULL:
        dw 0x00     ;프로세서 예약구간
        dw 0x00
        db 0x00
        db 0x00
        db 0x00
        db 0x00

    CODE:
        dw 0xFFFF   ;LIMIT ADRESS
        dw 0x0000   ;BASE ADRESS
        db 0x00     ;BASE ADRESS
        db 0x9A     ;1001 1010 A code segment descriptor (for your kernel, it should have type=0x9A) 
        db 0xCF     ;1100 1111
        db 0x00

    DATA:
        dw 0xFFFF
        dw 0x0000
        db 0x01
        db 0x92     ;1001 0010 A data segment descriptor (you cant write to a code segment, so add this with type=0x92) 
        db 0xCF     ;1100 1111
        db 0x00

    VIDEO:
        dw 0xFFFF
        dw 0x8000
        db 0x0B
        db 0x92
        db 0x40
        db 0x00

GDTEND:

times 510 - ($-$$) db 0x00

db 0x55
db 0xAA
第二阶段

[ORG 0x10000]
[BITS 32]

PROTECTED:
    mov ax, 0x10
    mov gs, ax
    mov ss, ax
    mov ds, ax
    mov es, ax
    mov fs, ax

    xor esp, esp    ; make stack
    mov esp, 0xFFFE
    mov ebp, 0xFFFE

    mov si, 0x18     ; setting for print message
    mov es, si
    mov bx, 0
    lea si, [message]   
    mov ah, 0x0f

MESSAGE:              ; print loop
    lodsb       
    cmp al, 0   
    je LOADKERNEL
    mov [es:bx], ax
    add bx, 2
    jmp MESSAGE

LOADKERNEL:
    jmp dword 0x08:0x10200   ; jump to C kernel

message: db 'Protected Mode Entered.', 0

times 512 - ($ - $$) db 0x00
还有C代码

void write_string();

void main(){
    write_string(0x09, "helloworld");
}

void write_string( int colour, const char *string )
{
    volatile char *video = (volatile char*)0xB8000;
    while( *string != 0 )
    {
        *video++ = *string++;
        *video++ = colour;
    }
}
我使用ld、gcc和objcopy将C代码转换为汇编代码

gcc -c -m32 -ffreestanding kernel.c -o kernel.o

ld -melf_i386 -Ttext 0x10200 -nostdlib kernel.o -o kernel.tmp

objcopy -O binary kernel.tmp kernel.img

cat bootloader.img secondstage.img kernel.img > Disk
像这样

我真的不明白为什么它不起作用


如果您需要更多信息,请留下评论。

您能给我们看看您的全局描述符表吗?这有助于我们了解段描述符中是否存在问题。此外,在32位保护模式下。您不需要段寄存器来操作内存,因为您可以使用32位寄存器直接访问它们,如
ESI
EDI
@TravorLiu我在段描述符中发现错误。我把它修好了。谢谢您的回答和建议。@TravorLiu我在段描述符中发现了错误。我把它修好了。谢谢你的回答和建议。