String 在真实硬件上显示随机字符,但在模拟器上不显示

String 在真实硬件上显示随机字符,但在模拟器上不显示,string,hardware,x86-16,display,bootloader,String,Hardware,X86 16,Display,Bootloader,目前我正在编写自己的引导加载程序。我已经成功地将其加载到qemu和VirturalBox上。然而,我在真正的硬件上有问题 下面是它应该是什么样子(这是在qemu上): 现在,这就是它在真实硬件上的外观: 有人能告诉我这里发生了什么,我能做些什么来解决这个问题 以下是printf代码: printf: pusha mov ah, 0x0e ; Teletype output function str_loop: mov al, [si] ; Load a chara

目前我正在编写自己的引导加载程序。我已经成功地将其加载到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"
读U盘:

;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  ................

首先,我将通过只实现必要的功能来简化代码。并不是说使用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

模拟器是很棒的工具,但在我的测试机上,我使用了DOS6.2的实际版本,它在诊断一些问题时非常方便。无论如何,我认为如果您实施Preamble,我相当有信心它将解决您的问题,或者如果没有其他问题,则排除在可能性之外。

首先,您不应该硬编码引导驱动器号。当BIOS将控制权传递给引导加载程序时,BIOS会传递从DL中引导的驱动器。您可以在磁盘读写中使用它。我想你是在真正的硬件上作为硬盘启动的?@MichaelPetch谢谢你的提示。是的,我正在从物理计算机的硬盘启动。我还尝试从其他磁盘号引导,我的引导加载程序显示一个错误,表示无法从磁盘读取。如我所料。如果不禁用中断并确保它们处于打开状态,会发生什么。(将CLI更改为STI)您没有向我们显示
includes/first_step.s
,因此我真的希望您正在设置SS:SP(比如可能将其设置为0x0000:0x7c00)这样,您就不会意外地读取BIOS可能使用的堆栈顶部的扇区,这可能会导致在进行磁盘读取时发生不好的事情。@MichaelPetch我已在编辑中附加了请求的代码。我在qemu中使用
sti
进行了测试,结果完全相同。我将不得不等到下周回到我的大学,在物理机器上测试它,因为我使用的是带UEFI引导的Mac,而不是BIOS引导。谢谢。下周你能给我解释一下为什么
org 0x7C00
在这么多教程中是错误的吗?还有,为什么我们要更改堆栈指针位置,而不是将其保持在原来的位置?这也是将堆栈指针移动到
0x9000:0x8000
,即0x98000吗?使用ORG并没有错,只是如果遇到一个BIOS将CS作为0x7c00传递,那么不是ORG 0的代码将无法工作。我之所以采用这种方法,主要是因为当我列出源代码时,0x1CD处的某些内容在十六进制转储和磁盘上也是0x1CD。BIOS不会将CS用作0x7c00。这将使物理地址从0x7c000开始。我想你的意思是0x07c0,它将把段的开始放在物理地址0x7C00,因为你没有使用默认为0x0000的组织。这意味着这是错误的
BOOT_SEG eq 0x7c0
应该是
BOOT_SEG eq 0x07c0
如果要使用任何字符串指令,如LODSB,则应确保正确设置方向位。在这种情况下,您希望它与您拥有的代码一起转发,因此需要使用CLD来清除它(clear=forward/set=backward)。您不能假设BIOS将清除方向标志。
printf:
    mov ah, TTY
 .L0:
    lodsb
    or  al, al
    jnz .J1
    ret
  .J1:
    int VIDEO
    jmp .L0