sách gpt4 ai đã đi

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

In lại 作者:行者123 更新时间:2023-12-05 00:58:21 29 4
mua khóa gpt4 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

trở về

; 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
trở về

; 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
trở về

; 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

trở về

; 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:
trở về

;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

trở về

;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

trở về

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
trở về

.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

注意:故障码是 KHÔNG hiện hữu bios_print_string常规,因为它在其他地方完美无缺。

1 Câu trả lời

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

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

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

29 4 0
Bài viết được đề xuất: yacc - 一个程序中的多个 YACC 语法
Bài viết được đề xuất: regex - 在 Vim 中将 .0D0 添加到数字末尾
Bài viết được đề xuất: R - 从 colMeans 函数创建数据帧
Bài viết được đề xuất: xaml - 更改所有页面的背景颜色WP7
行者123
Hồ sơ cá nhân

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá Didi Taxi miễn phí
Mã giảm giá Didi Taxi
Giấy chứng nhận ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com