裸机环境中意外的内存损坏[已解决]

问题描述 投票:0回答:1

我有一个简单的 32 位内核,它被如下所示的引导加载程序成功加载

[org 0x7c00]
; we can also alter the data segment register (ds) accordingly:
; mov ds, 0x7c0 (it will be 0x7c00 because address bus is 20-bit)

KERNEL_LOCATION equ 0x1000
BOOT_DISK equ 0

; setting up the stack and tiny memory model
xor ax, ax
mov es, ax
mov ds, ax
mov bp, 0x8000
mov sp, bp


; loading the kernel in memory location 0x1000
call read_disk

; ; Set up VESA graphics mode (example: mode 0x101 - 640x480, 16 colors)
; mov ax, 0x4F02     ; VESA function to set video mode
; mov bx, 0x101      ; Mode number for desired resolution/color depth
; int 0x10           ; Call BIOS interrupt to set the video mode

; initialize protected mode
init_pm:

    ; clear the screen using bios before disabling it
    mov ax, 0x0003 
    int 10h

    ; clear interrupts
    mov bx,suc
    ;call print_string
    
    ; some delay just for looking cool :)
    ;call delay
    ;mov ax, 0x0003
    ;int 10h
 
    cli
    ; this instruction loads the gdt location and size into the gdtr (gdt register) in the cpu
    lgdt [GDT_descriptor]

    ; changing the first bit of cr0 register (0th control register) which corresponds to [ Protected Mode Enable ]
    mov eax, cr0
    or eax, 1
    mov cr0, eax

    ; far jump!!
    jmp CODE_SEG:start_protected_mode

%include "gdt.asm"
%include "read_disk.asm"
;%include "print_string.asm"
%include "delay.asm"

; this tells the assembeler (in this case nasm) to compile the
; code to 32 bit machine code now on
[bits 32]
start_protected_mode:

    ; changing stack and memory segments model
    mov eax, DATA_SEG
    mov ds, eax
    mov ss, eax
    mov es, eax
    mov fs, eax
    mov gs, eax

    mov ebp, 0x90000        ; 32 bit stack base pointer
    mov esp, ebp

    jmp KERNEL_LOCATION

suc:
    db "entering 32-bit mode...",0
jmp $



times 510-($-$$) db 0
dw 0xaa55

我的问题是我的内核 .text 部分将覆盖内核的其他部分,因此导致随机行为

这是用c:编写的内核代码

#include "std/stdout.h"
#include "terminal/terminal.h"



void func1(){
        for (int i = 0; i < 33; i++)
    {
        /* code */
    }
}
void func2(){
        for (int i = 0; i < 33; i++)
    {
        /* code */
    }
}
void func3(){
        for (int i = 0; i < 33; i++)
    {
        /* code */
    }
}
void func4(){
    for (int i = 0; i < 33; i++)
    {
        /* code */
    }
    
}


void kernel_start(){
    prepare_terminal();
    background_color = 32;
}

注意:不知何故,只有其中 3 个函数不会导致问题,因此我怀疑再添加一个函数会超出某种限制

我尝试更改链接器脚本以添加对齐,因为我怀疑这是由于每个部分的大小有限,但它没有帮助,或者也许我做错了

这是我当前的链接器脚本:

ENTRY(_start)

SECTIONS {
    . = 0x1000;

    .text : {
        *(.text)
    }
    
    .data : {
        *(.data)
    }

    .bss : {
        *(.bss)
    }
}

损坏的代码: normal

正常: broken code

c operating-system bootloader bare-metal linker-scripts
1个回答
0
投票

原来我的问题是因为我只从磁盘读取了10个扇区,这导致程序中途停止并产生一些意想不到的问题。

我所做的是增加要读取的扇区数量:

read_disk:

    ; bios read functions
    mov ah, 0x02

    ; number of sectors to be read
    ; mov al, 10                    <========! HERE
    mov al, 40    

    ; chs addressing
    mov ch, 0x00 ; cylender
    mov dh, 0x00 ; head
    mov cl, 0x02 ; sector (reading the first sector after the boot sector sectors start at 1)


    ; setting the bx to the address we want to load our read disk
    mov bx, KERNEL_LOCATION

    mov dl, BOOT_DISK

    int 0x13  
    ; jump to error handler if c flag is one
    ; jc disk_error

    ; returning to the caller address
    ret

; error handler
disk_error:
    mov bx, error_msg
    ;call print_string
    jmp $

error_msg:
    ; null terminating string :)
    db "error reading disk",0

它解决了我的问题:)

© www.soinside.com 2019 - 2024. All rights reserved.