Operating system C内核可以';t打印字符串
我写了一个内核来打印hello world。但它不起作用, hello world未打印。 组装打印效果良好 我使用GCC和NASM进行交叉编译和组装 这是我的引导程序,第二阶段代码和C代码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
[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我在段描述符中发现了错误。我把它修好了。谢谢你的回答和建议。