gpt4 book ai didi

assembly - 引导加载程序代码有时会崩溃(三重故障?)计算机

转载 作者:行者123 更新时间:2023-12-05 00:58:21 28 4
gpt4 key购买 nike

我的自定义引导加载程序中有代码从地址 0x8E00 处的 512 字节缓冲区复制内存。进入高内存,0x100000和更高。这在某些计算机上运行良好,而在其他计算机上崩溃(我假设是三重故障)。此代码在 Bochs x86 模拟器中也能正常工作。

我尝试用 rep movsb 替换自定义段偏移复制循环, 设置 esiedi到适当的地址,发现这在某些计算机上也会出现故障。这有什么理由失败吗?

引导加载.asm:

; Portions of this code are under the MikeOS license, as follows:
;
; ==================================================================
; Copyright (C) 2006 - 2014 MikeOS Developers -- http://mikeos.sourceforge.net
;
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
;
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
;
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
;
; * Neither the name MikeOS nor the names of any MikeOS contributors
; may be used to endorse or promote products derived from this software
; without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY MIKEOS DEVELOPERS AND CONTRIBUTORS "AS IS"
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
; ARE DISCLAIMED. IN NO EVENT SHALL MIKEOS DEVELOPERS BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
; CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
; USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
; ==================================================================

BOOTLOADER_SECTORS equ 3 ; includes first sector, loaded by

BIOS

; a boot sector that enters 32-bit protected mode
BITS 16
ORG 0x7c00

jmp short bootloader_start ; Jump past disk description section
nop ; Pad out before disk description


; ------------------------------------------------------------------
; Disk description table, to make it a valid floppy
; Note: some of these values are hard-coded in the source!
; Values are those used by IBM for 1.44 MB, 3.5" diskette

OEMLabel db "OLIVEOS " ; Disk label
BytesPerSector dw 512 ; Bytes per sector
SectorsPerCluster db 1 ; Sectors per cluster
ReservedForBoot dw BOOTLOADER_SECTORS ; Reserved sectors for boot record
NumberOfFats db 2 ; Number of copies of the FAT
RootDirEntries dw 224 ; Number of entries in root dir
; (224 * 32 = 7168 = 14 sectors to read)
LogicalSectors dw 2880 ; Number of logical sectors
MediumByte db 0F0h ; Medium descriptor byte
SectorsPerFat dw 9 ; Sectors per FAT
SectorsPerTrack dw 18 ; Sectors per track (36/cylinder)
Sides dw 2 ; Number of sides/heads
HiddenSectors dd 0 ; Number of hidden sectors
LargeSectors dd 0 ; Number of LBA sectors
DriveNo dw 0 ; Drive No: 0
Signature db 41 ; Drive signature: 41 for floppy
VolumeID dd 00000000h ; Volume ID: any number
VolumeLabel db "OLIVEOS "; Volume Label: any 11 chars
FileSystem db "FAT12 " ; File system type: don't change!

KERNEL_OFFSET equ 0x100000 ; kernel load offset
STACK_LOCATION equ 0x7c00 ; stack location
MEM_MAP_ENTRIES equ 0x5000 ; memory map length offset
MEM_MAP_OFFSET equ 0x5004 ; memory map offset

bootloader_start:
; NOTE: A few early BIOSes are reported to improperly set DL

cmp dl, 0
je no_change
mov [BOOT_DRIVE], dl ; Save boot device number
mov ah, 8 ; Get drive parameters
int 13h
jc disk_error
and cx, 3Fh ; Maximum sector number
mov [SectorsPerTrack], cx ; Sector numbers start at 1
movzx dx, dh ; Maximum head number
add dx, 1 ; Head numbers start at 0 - add 1 for total
mov [Sides], dx

no_change:
mov eax, 0 ; Needed for some older BIOSes

cli
xor ax, ax ; make AX zero
mov ds, ax ; so we point our segment registers to zero
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax

jmp 0x0000:bootloader_landing ; far jump to clear cs to 0

bootloader_landing:
mov bp, STACK_LOCATION ; set up stack
mov sp, bp

sti

mov si, MSG_STARTING_BOOTLOADER
call bios_print_string

call load_bootloader ; load the rest of the bootloader (if we don't do it first,
; something is very likely going to mess up)

pusha
mov di, MEM_MAP_OFFSET
jmp bios_get_memory ; get memory map for kernel
bios_get_memory_return:
popa

mov bp, STACK_LOCATION ; set up stack again (bios_get_memory trashed our stack)
mov sp, bp

jmp second_stage ; transfer control to second stage!

; loads the rest of this bootloader
load_bootloader:
mov bx, second_stage ; read to 0x7e00 (right after this 512 byte code segment)
mov al, BOOTLOADER_SECTORS-1 ; sectors to read
mov dl, [BOOT_DRIVE] ; drive
mov cl, 0x02 ; start sector
mov ch, 0x00 ; cylinder
mov dh, 0x00 ; head
mov ah, 0x02 ; BIOS read sector function

push ax ; store AX on stack so later we can recall
; how many sectors were request to be read,
; even if it is altered in the meantime

int 0x13 ; call BIOS

jc disk_error ; jump if error (carry flag set)

pop dx ; restore from stack (was AX before)
cmp dl, al ; if AL (sectors read) != DH (sectors expected)
jne disk_error ; display error message

ret

; displays error message and hangs
disk_error:
mov si, DISK_ERROR_MSG
call bios_print_string

sti
.halt:
hlt
jmp .halt

; -----------------------------------------------------------------
; BOOTLOADER SUBROUTINES:
;
bios_print_string:
pusha

mov ah, 0x0e ; int 10h teletype function

.repeat:
lodsb ; Get char from string

cmp al, 0
je .done ; If char is zero, end of string

int 0x10 ; Otherwise, print it
jmp .repeat ; And move on to next char

.done:
popa
ret

; prints 16 bit hex value from AX
bios_print_2hex:
push cx

mov cx, 16-4
.repeat:
push ax

shr ax, cl
and ax, 0xf
cmp ax, 9
jle .print

add ax, 'A'-'9'-1

.print:
add ax, '0'
mov ah, 0x0e
int 0x10

pop ax

cmp cx, 0
je .done

sub cx, 4
jmp .repeat;
.done:
pop cx
ret

; prints 32 bit hex value from AX
bios_print_4hex:
push eax

shr eax, 16
call bios_print_2hex

pop eax
and eax, 0xffff
call bios_print_2hex

ret

; global variables
BOOT_DRIVE db 0
MSG_STARTING_BOOTLOADER db "OliveOS", 0
MSG_STARTING_SECOND_STAGE db " has started!", 0
MSG_READING db ".", 0
MSG_READING2 db "!", 0
DISK_ERROR_MSG db "Disk read error!", 0
MSG_REG_DUMP db 0xD, 0xA, "INTERNAL REG DUMP", 0xD, 0xA, 0
NEWLINE db 0xD, 0xA, 0

; bootsector padding
times 510-($-$$) db 0
dw 0xaa55

BITS 16

second_stage:
mov si, MSG_STARTING_SECOND_STAGE
call bios_print_string

;call bios_enable_a20
call load_kernel

jmp switch_to_pm ; switch to protected mode, we won't return from here

BITS 32
; this is where we arrive after switching to and initializing protected mode
begin_pm:
call kbd_enable_a20
call fast_enable_a20

call CODE_SEG:KERNEL_OFFSET ; now call the kernel!

.halt:
hlt ; hang
jmp .halt

BITS 16

load_dest:
dd KERNEL_OFFSET

; loads the kernel from the floppy image
load_kernel:
mov ax, BOOTLOADER_SECTORS ; start logical sector
mov cx, 200 ; number of sectors to read

.continue:
cmp cx, 0
je .done

pusha
mov ebx, 0x8E00 ; write to 0x8E00 a temporary 512 byte buffer
call bios_disk_load ; load bytes to buffer

mov si, MSG_READING
call bios_print_string
popa

pusha ; copy bytes in buffer to destination
call switch_to_unreal ; switch to unreal mode to access high memory

mov cx, 0x200 ; copy 512 bytes
mov ebx, 0x8E00 ; read from 0x8E00
mov edx, dword [load_dest] ; load destination address

.copy:
cmp cx, 0
je .done_copying

mov eax, dword [fs:ebx]
mov dword [fs:edx], eax ; commenting out this line (the actual write) will work on any computer

add ebx, 4
add edx, 4

sub cx, 4
jmp short .copy

.done_copying:
call switch_to_real ; switch back to real mode
popa

add dword [load_dest], 0x200 ; add 512 bytes to output pointer
inc ax ; increment logical sector
dec cx ; decrement loop counter

jmp .continue ; continue reading
.done:
ret

;sets up LBA address in AX for INT 13H
logical_int13_setup:
push bx
push ax

mov bx, ax ; Save logical sector

mov dx, 0 ; First the sector
div word [SectorsPerTrack]
add dl, 0x01 ; Physical sectors start at 1
mov cl, dl ; Sectors belong in CL for int 13h
mov ax, bx

mov dx, 0 ; Now calculate the head
div word [SectorsPerTrack]
mov dx, 0
div word [Sides]
mov dh, dl ; Head/side
mov ch, al ; Track

pop ax
pop bx

mov dl, byte [BOOT_DRIVE] ; Set correct device

ret

;bios_disk_load: loads logical sector in AX to ES:BX
bios_disk_load:
call logical_int13_setup ; setup our parameters

mov ah, 0x2 ; INT 0x13 function
mov al, 0x1 ; load 1 sector

int 0x13

jc disk_error ; jump if error (carry flag set)

cmp al, 1 ; if AL (sectors read) != 1 (sectors expected)
jne disk_error ; display error message

ret

bios_reg_dump:
pusha

mov si, MSG_REG_DUMP
call bios_print_string

mov si, .MSG_AX
call bios_print_string
call bios_print_4hex
mov si, NEWLINE
call bios_print_string

mov si, .MSG_BX
call bios_print_string
mov eax, ebx
call bios_print_4hex
mov si, NEWLINE
call bios_print_string

mov si, .MSG_CX
call bios_print_string
mov eax, ecx
call bios_print_4hex
mov si, NEWLINE
call bios_print_string

mov si, .MSG_DX
call bios_print_string
mov eax, edx
call bios_print_4hex
mov si, NEWLINE
call bios_print_string

mov si, .MSG_CS
call bios_print_string
mov eax, cs
call bios_print_4hex
mov si, NEWLINE
call bios_print_string

mov si, .MSG_DS
call bios_print_string
mov eax, ds
call bios_print_4hex
mov si, NEWLINE
call bios_print_string

mov si, .MSG_ES
call bios_print_string
mov eax, es
call bios_print_4hex
mov si, NEWLINE
call bios_print_string

mov si, .MSG_FS
call bios_print_string
mov eax, fs
call bios_print_4hex
mov si, NEWLINE
call bios_print_string

mov si, .MSG_GS
call bios_print_string
mov eax, gs
call bios_print_4hex
mov si, NEWLINE
call bios_print_string

popa
ret

.MSG_AX db "EAX: 0x", 0
.MSG_BX db "EBX: 0x", 0
.MSG_CX db "ECX: 0x", 0
.MSG_DX db "EDX: 0x", 0
.MSG_CS db "CS: 0x", 0
.MSG_DS db "DS: 0x", 0
.MSG_ES db "ES: 0x", 0
.MSG_FS db "FS: 0x", 0
.MSG_GS db "GS: 0x", 0

%include "source/bootload/gdt.asm"
%include "source/bootload/protected_mode.asm"
%include "source/bootload/memory.asm"

times (BOOTLOADER_SECTORS*512)-($-$$) db 0

注意:故障码是 不是 bios_print_string常规,因为它在其他地方完美无缺。

最佳答案

我找到了我的问题的答案。写信mov dword [fs:edx], eax失败,不是因为 fsedx包含无效的段和地址,但因为在写入地址之前未启用 A20 线 0x100000和更高。相反,它后来被启用。

一些 BIOS,如 Bochs,已经设置了 A20 线,允许代码运行。其他人没有设置 A20 行,因此写入地址模 0x100000 , 地址 0x000000和更高。这是 IVT(中断向量表)存储在内存中的地方,如果被覆盖,则可以轻松地从未处理的中断和崩溃或挂起计算机中创建三重故障。解决方案?在写入高地址之前设置 A20 线。

关于assembly - 引导加载程序代码有时会崩溃(三重故障?)计算机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32674066/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com