我现在正在编写自己的引导程序。我已经能够成功地将其加载到qemu和VirturalBox上。但是,我在真正的硬件上有问题。
这是它的外观(在qemu上):
有人可以让我知道这是怎么回事,以及我可以做些什么来解决这个问题。
这是printf
代码:
printf:
pusha
mov ah, 0x0e ; Teletype output function
str_loop:
mov al, [si] ; Load a character byte to al
cmp al, 0
jne print_char ; if al != 0, jmp to print_char
popa
ret
print_char:
int 0x10 ; 0x10 interrupt
inc si ; add 1 to si
jmp str_loop
printh:
printh:
push cx
push di
push bx
mov si, HEX_PATTERN ; Load HEX_PATTERN memory location to si
mov cl, 12
mov di, 0
.hexLoop:
mov bx, dx ; copy dx to bx to preserve original hex value
shr bx, cl ; Shift value in bx 12 bits (3 bytes) right
and bx, 0x000F ; mask first 3 digits
mov bx, [bx + HEX_TABLE] ; load ascii character from HEX_TABLE into bx
mov [HEX_PATTERN + di], bl ; insert byte bl into correct spot in HEX_PATTERN
sub cl, 4 ; change bits shifted in next iteration
inc di ; add 1 to insertion location in HEX_PATTERN
cmp di, 4 ; since HEX_PATTERN.length = 4:
je .exit ; if (di == 4) {exit the loop}
jmp .hexLoop
.exit:
call printf ; print HEX_PETTERN which is now populated
pop bx
pop di
pop cx
ret
HEX_PATTERN db '****h', 0Ah, 0Dh, 0
HEX_TABLE db "0123456789ABCDEF"
读取磁盘:
;in=============================
;AL - sectors to read count
;CL - sector to read into memory
;DI - location to load
;out===========================
;CF - error
read_disk:
pusha
mov ah, 02h ;We want to read a device
mov dl, 80h ;Spcificly a hard disk. Note: Floppy/SSDs are 00h
mov ch, 0 ;Start at clyender 1
mov dh, 0 ;Start at head 1
;Address access pointer is where the memory is stored
;This is at es:bx
push bx
mov bx, 0 ;Set bx to zero
mov es, bx ;Set segment to zero
pop bx
mov bx, di ;Set offset to the address after our bootloader
int 13h ;Read from disk
popa
ret
最后是主要代码:
org 0x7c00 ; add to offsets
bits 16
section .text
global main
main:
cli ;Disable interupts
jmp 0x0000:FIRST_STEP ;Make sure we load the correct address
%include "includes/first_step.s"
mov si, BOOTLOADER_STARTED
call printf
push ax
xor ax, ax
mov dl, 80h
int 13h
mov si, DISK_RESET_MSG
call printf
call testA20
mov dx, ax
call printh
call enableA20
call testA20
mov dx, ax
call printh
mov al, 1
mov cl, 2
mov di, [SECTOR_TWO_MEMORY_LOCATION]
call read_disk
jc disk_read_error
jmp [SECTOR_TWO_MEMORY_LOCATION]
hlt
disk_read_error:
mov si, DISK_ERROR_MSG
call printf
hlt
%include "includes/bootlibrary.s"
SECTOR_TWO_MEMORY_LOCATION dw 0x7C00 + 512
BOOTLOADER_STARTED db "DKBootLoader has started", 0Ah, 0Dh, 0
DISK_RESET_MSG db "Reset disk", 0Ah, 0Dh, 0
DISK_ERROR_MSG db "Error reading disk. DKOS cannot boot", 0
times 510-($-$$) db 0 ; make sure file is 510 bytes in size
dw 0xaa55 ; write boot signiture
mov si, DISK_SUCSESSFULLY_READ
call printf
mov si, CHECKING_LONG_MODE
call printf
call check_long_mode
push ax
test ax, 0
pop dx
call printh
je long_mode_enabled
long_mode_disabled:
mov si, LONG_MODE_DISABLED_MSG
call printf
hlt
long_mode_enabled:
mov si, LONG_MODE_ENABLED_MSG
call printf
hlt
%include "check_long_mode.s"
DISK_SUCSESSFULLY_READ db "Disk sucsessfully read. In second sector", 0Ah, 0Dh, 0
CHECKING_LONG_MODE db "Checking long mode", 0Ah, 0Dh, 0
LONG_MODE_ENABLED_MSG db "Long mode is enabled", 0Ah, 0Dh, 0
LONG_MODE_DISABLED_MSG db "Long mode is not avaliable", 0Ah, 0Dh, 0
times (512*2)-($-$$) db 0 ; make sure file is 510 bytes in size
如果您还需要其他功能,请告诉我。我认为这可能会失败。
最后,这是一个十六进制转储:
00000000: faea 067c 0000 31c0 8ed0 8ed8 8ec0 8ee0 ...|..1.........
00000010: 8ee8 bc00 7cfc be7f 7de8 3900 5031 c0b2 ....|...}.9.P1..
00000020: 80cd 13be 9a7d e82c 00e8 9300 89c2 e834 .....}.,.......4
00000030: 00e8 c200 e888 0089 c2e8 2900 b001 b102 ..........).....
00000040: 8b3e 7d7d e862 0072 05ff 267d 7df4 bea7 .>}}.b.r..&}}...
00000050: 7de8 0100 f460 b40e 8a04 3c00 7502 61c3 }....`....<.u.a.
00000060: cd10 46eb f351 5753 be91 7cb1 0cbf 0000 ..F..QWS..|.....
00000070: 89d3 d3eb 83e3 0f8b 9f99 7c88 9d91 7c80 ..........|...|.
00000080: e904 4783 ff04 7402 ebe6 e8c8 ff5b 5f59 ..G...t......[_Y
00000090: c32a 2a2a 2a68 0a0d 0030 3132 3334 3536 .****h...0123456
000000a0: 3738 3941 4243 4445 4660 b402 b280 b500 789ABCDEF`......
000000b0: b600 53bb 0000 8ec3 5b89 fbcd 1361 c360 ..S.....[....a.`
000000c0: a1fe 7d53 bbff ff8e c35b bb0e 7e26 8b17 ..}S.....[..~&..
000000d0: 39d0 7405 61b8 0100 c3a1 ff7d 53bb ffff 9.t.a......}S...
000000e0: 8ec3 5bbb 0f7e 268b 1739 d074 0561 b801 ..[..~&..9.t.a..
000000f0: 00c3 6131 c0c3 60b8 0124 cd15 e8c0 ff83 ..a1..`..$......
00000100: f801 744c fbe8 5000 b0ad e664 e849 00b0 ..tL..P....d.I..
00000110: d0e6 64e8 4900 e460 50e8 3c00 b0d1 e664 ..d.I..`P.<....d
00000120: e835 0058 0c02 e660 e82d 00b0 aee6 64e8 .5.X...`.-....d.
00000130: 2600 fbe8 89ff 83f8 0174 15e4 920c 02e6 &........t......
00000140: 92e8 7bff 3c01 7408 be66 7de8 07ff ebfe ..{.<.t..f}.....
00000150: be6f 7de8 fffe 61c3 e464 a802 75fa c3e4 .o}...a..d..u...
00000160: 64a8 0174 fac3 4e6f 2041 3230 0a0d 0041 d..t..No A20...A
00000170: 3230 2045 6e61 626c 6564 0a0d 0000 7e44 20 Enabled....~D
00000180: 4b42 6f6f 744c 6f61 6465 7220 6861 7320 KBootLoader has
00000190: 7374 6172 7465 640a 0d00 5265 7365 7420 started...Reset
000001a0: 6469 736b 0a0d 0045 7272 6f72 2072 6561 disk...Error rea
000001b0: 6469 6e67 2064 6973 6b2e 2044 4b4f 5320 ding disk. DKOS
000001c0: 6361 6e6e 6f74 2062 6f6f 7400 0000 0000 cannot boot.....
000001d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000001e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000001f0: 0000 0000 0000 0000 0000 0000 0000 55aa ..............U.
00000200: be6c 7ee8 4ffe be97 7ee8 49fe e818 0050 .l~.O...~.I....P
00000210: a900 005a e84e fe74 07be c37e e836 fef4 ...Z.N.t...~.6..
00000220: beac 7ee8 2ffe f460 669c 6658 6689 c166 ..~./..`f.fXf..f
00000230: 3500 0020 0066 5066 9d66 9c66 5866 31c8 5.. .fPf.f.fXf1.
00000240: 7425 66b8 0000 0080 0fa2 663d 0100 0080 t%f.......f=....
00000250: 7215 66b8 0100 0080 0fa2 66f7 c200 0000 r.f.......f.....
00000260: 2074 0461 31c0 c361 b801 00c3 4469 736b t.a1..a....Disk
00000270: 2073 7563 7365 7373 6675 6c6c 7920 7265 sucsessfully re
00000280: 6164 2e20 496e 2073 6563 6f6e 6420 7365 ad. In second se
00000290: 6374 6f72 0a0d 0043 6865 636b 696e 6720 ctor...Checking
000002a0: 6c6f 6e67 206d 6f64 650a 0d00 4c6f 6e67 long mode...Long
000002b0: 206d 6f64 6520 6973 2065 6e61 626c 6564 mode is enabled
000002c0: 0a0d 004c 6f6e 6720 6d6f 6465 2069 7320 ...Long mode is
000002d0: 6e6f 7420 6176 616c 6961 626c 650a 0d00 not avaliable...
000002e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000002f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000300: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000310: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000320: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000330: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000340: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000350: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000360: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000370: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000380: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000390: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000003a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000003b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000003c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000003d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000003e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000003f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
这是什么原因,我该怎么解决?我也尝试读取不同的磁盘。
那也不行。
除了字符串显示不正确之外,第二个扇区也似乎都无法加载。
我还用文件/dev/disk2
来运行qemu,这是我的硬盘驱动器。那里没有问题。仅在物理计算机上。
修改:
根据要求,这是first_steps.s:
FIRST_STEP:
;Zero out all general purpose registers
xor ax, ax
mov ss, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov sp, main ;Set our stack pointer to the address of our 'main'lable
cld ;Clear the direction flag - controls order we read strings
答案 0 :(得分:-2)
首先,我将仅通过实现必要的功能来简化代码。并不是说使用ORG是错误的,但是此序言保证了它甚至可以与其中的一些新奇BIOS一起使用。我认为假设您没有使用链接器是安全的,因此在平面二进制文件中,段没有任何好处。
序言
BOOT_SEG equ 0x7c00
TTY equ 0x0E
VIDEO equ 0x10
jmp BOOT_SEG:Start ; Guarantee that CS = 0x7c00:Start
Start:
mov ax, cs
mov ds, ax
mov es, ax ; Initialize primary segment registers
; Then set stack pointer to a safe place (*98000H*) but this does make the
; assumption that machine has at least 1M of ram.
cli
mov ax, 0x9000
mov ss, ax
mov sp, 0x8000
sti
显示以null结尾的字符串也可以进行优化。 BIOS不会更改任何不需要的内容,因此,如果有的话,SI会指向内存中的下一个字符串。
printf:
mov ah, TTY
.L0:
lodsb
or al, al
jnz .J1
ret
.J1:
int VIDEO
jmp .L0
乳化器是很棒的工具,但是在我的测试机上,我使用的是DOS 6.2的实际版本,在解决某些问题时非常方便。无论如何,我认为如果您实施Preamble,我很有信心它将解决您的问题,或者如果没有别的,那就排除在可能性之外。