【问题标题】:keep getting reoccurring smiley faces on bootloader hello world program在引导加载程序 hello world 程序上不断出现笑脸
【发布时间】:2021-10-04 16:17:07
【问题描述】:

您好,这个问题一直在我不断出现的笑脸。我的工作涉及 2 个文件。

第一个是后台引导加载程序,里面的所有东西都很好用,没有改变,但第二个文件支持成为一个 hello world,但只会产生重复出现的笑脸。

program_space equ 0x7e00                          ; program space variable equates to 0x7e00. 
                                                  ; 0x7e00 is 512 bytes after 0x7c00 in memory  
[org 0x7c00]                                      ; declares the origin at the location 0x7c00
                                                  ; disk number is stored in al register
mov bp, 0x7c00                                    ; moves 0x7c00 to the base pointer, CS:IP 
                                                  ; CS:IP always points to physical address 0x07C00.
mov sp, bp                                        ; moves the base pointer bp to the stack pointer sp
; the basic_input_output_system(bios) automatically stores the disk number that the program was loaded from into the dl register
mov [boot_disk], dl                               ; moves dl contents to boot disk
mov al, [program_space]                           ; moves the program space to al

mov ah, 0x0e                                      ; BIOS.Teletype
mov al, '1'                                       ; Moves '1' to al register
int 0x10                                          ; calls print
mov al, ' '                                       ; Moves ' ' to al register
int 0x10                                          ; calls print
mov bx, Hello_World                               ; move Hello_World labels position to bx[16 bit]
call print_string                                 ; calls print_string function

mov ah, 0x0e                                      ; BIOS.Teletype
mov al,  0xa                                      ; move down 1 line.
int 0x10                                          ; print al
mov al,  0xd                                      ; move position to start of line.
int 0x10                                          ; print al
call read_disk                                    ; calls read_disk function position
mov bx, disk_read_true                            ; moves disk_read_true to bx register
call print_string                                 ; calls print_string function 
jmp program_space                                 ; jumps to program_space
jmp $                                             ; declares an infinite loop

print_string:                                     ; declares the label location of print_string function
push ax                                           ; pushes the ax register
push bx                                           ; pushes the bx register
mov ah, 0x0e                                      ; BIOS.Teletype
     .loop:                                       ; declares the label location of loop
     cmp [bx], byte 0                             ; compares a size of 0 bytes to bx register
     je .exit                                     ; if equal jump to .exit label
               mov al, [bx]                       ; moves bx contents to al register
               int 0x10                           ; declares print
               inc bx                             ; increment the bx register
               jmp .loop                          ; jump to .loop to create a for loop
.exit:                                            ; declares the label location of exit
pop ax                                            ; pops the ax register
pop bx                                            ; pops the bx register
ret                                               ; returns to position to call print_string

read_disk:                                        ; declares read_disk position
mov ah, 0x02                                      ; moves bios read sectors into memory to ah
mov bx, program_space                             ; moves the program space to bx
mov al, 4                                         ; reads 4 sectors aka 2000 bytes, or 2 kilobytes
mov dl, [boot_disk]                               ; moves the value of boot disk into dl
mov ch, 0x00                                      ; moves cyclinder 0 of hard drive into ch
mov dh, 0x00                                      ; moves cyclinder 0 of hard drive into dh
mov cl, 0x02                                      ; Moves 2 cylinders to cl
int 0x13                                          ; interrupt commands the bios to read the disk
jc disk_read_false                                ; jumps conditionaly to disk read false
ret                                               ; returns from read_disk to its call
disk_read_false:                                  ; declares the disk_read_false location
mov bx, disk_read_error                           ; moves the disk read error label to bx register
call print_string                                 ; declares a call to the print_string function
jmp $                                             ; declares infinite loop

Hello_World:        db 'Hello World!',0           ; declares the hello World position and the string Hello World!
disk_read_error:    db 'Disk Read = False;',0     ; declares disk_read_error position
disk_read_true:     db 'Disk Read = True;',0      ; declares the disk_read_true position
boot_disk:          db 0                          ; declares boot_disk position defines a bite of 0

times 510-($-$$) db 0           ; fills the drive with 510 bytes of ($-$$).
                                ; each ($-$$) is a double byte of 0. 
                                ; that makes up 510/512 bytes for the bootloader 
dw 0xaa55                       ; declares a bootloader using a double word occupying 2/512 bytes 
                                ; total is 512/512 bytes = 2/512 bytes + 510/512 bytes

这是下面有问题的文件



                                                  ; Ralf Brown's Interrupt List
[org 0x7e00]                                      ; program space variable equates to 0x7e00. 
                                                  ; 0x7e00 is 512 bytes after 0x7c00 in memory 
mov ah, 0x0e                                      ; BIOS.Teletype
mov al,  0xa                                      ; **move down 1 line.**
int 0x10                                          ; **declares print**
mov al,  0xd                                      ; **move position to start of line.**
int 0x10                                          ; **declares print**
mov bx, extended_space_true
call print_string

jmp activate_protected_mode

activate_protected_mode:
call activate_A20
cli
lgdt [g.d.t_descriptor]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp codeseg:protected_mode_start

activate_A20:
in al, 0x92
or al, 2
out 0x92, al
ret

[bits 32]

protected_mode_start:
mov ax, dataseg
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 90000
mov esp, ebp
mov [0xb8000], byte 'H'
mov [0xb8002], byte 'e'
mov [0xb8004], byte 'l'
mov [0xb8006], byte 'l'
mov [0xb8008], byte 'o'
mov [0xb800a], byte ' '
mov [0xb800c], byte 'W'
mov [0xb800e], byte 'o'
mov [0xb8010], byte 'r'
mov [0xb8012], byte 'l'
mov [0xb8014], byte 'd'
mov [0xb8016], byte '!'
jmp $


g.d.t.asm:
g.d.t_null_descriptor:
dd 0
dd 0
g.d.t_code_descriptor:                           ; **declares g.d.t_code_descriptor location**
dw 0xffff                                        ; **limit**
dw 0x0000                                        ; **limit base(low)**
db 0x00                                          ; **Base (medium)**
db 10011010b                                     ; **flags**
db 11001111b                                     ; **flags + upper limit**
db 0x00                                          ; **base (high)**

g.d.t_data_descriptor:                           ; **declares g.d.t_data_descriptor location**
dw 0xffff                                        ; **limit**
dw 0x0000                                        ; **limit base(low)**
db 0x00                                          ; **Base (medium)**
db 10010010b                                     ; **flags**
db 11001111b                                     ; **flags + upper limit**
db 0x00                                          ; **base (high)**

g.d.t_end:

g.d.t_descriptor:
g.d.t_size: 
dw g.d.t_end - g.d.t_null_descriptor - 1
dd g.d.t_null_descriptor

codeseg equ g.d.t_code_descriptor - g.d.t_null_descriptor
dataseg equ g.d.t_data_descriptor - g.d.t_null_descriptor

print_string:                                     ; **declares position of print_string function**
push ax                                           ; **pushes the ax register**
push bx                                           ; **pushes the bx register**
mov ah, 0x0e                                      ; **BIOS.Teletype**
.loop:                                            ; **declares position of loop**
cmp [bx], byte 0                                  ; **compares a size of 0 bytes to bx**
je .exit                                          ; **if the result is equal jump to exit**
mov al, [bx]                                      ; **declares move value at bx to al.**
int 0x10                                          ; **declares print**
inc bx                                            ; **increment the bx as a for loop**
jmp .loop                                         ; **jump to the for loop**
.exit:                                            ; **labels position of exit**
pop ax                                            ; **pops the ax register**
pop bx                                            ; **pops the bx register**
ret                                               **; returns to position of call printstring**


extended_space_true: db 'Extended Space = True;',0
times 2048-($-$$) db 0

我对代码的解释在旁边

【问题讨论】:

  • 请参观而不是垃圾邮件 30 次“请帮助我”这只是粗鲁,不会增加您得到任何答案的概率
  • 正如@Björn 指出的那样,请查看tour,并查看how to ask a good question 上的部分。

标签: assembly nasm x86-16 bootloader


【解决方案1】:

第一个是后台引导加载程序,那里的一切都很好,没有改变

对您而言,第一阶段引导加载程序中的代码似乎运行良好,但仍然包含太多错误!正如我在my answer to your previous question 中解释的那样,您需要自己设置段寄存器才能正确操作代码。永远不要相信预先存在的价值观!唯一的例外是包含 BootDrive 代码的 DL 寄存器。

mov  bp, 0x7C00
xor  ax, ax
mov  ds, ax
mov  es, ax
mov  ss, ax  \ Always keep these together and in this order, not kidding!
mov  sp, bp  /

而且我不会重复我在之前的回答中写的内容,但我可以说,如果你会采用我的 print_string 子例程版本(并因此使用类似的 BIOS.Teletype 函数应该),您今天不会显示以错误顺序恢复寄存器(被压入堆栈)的代码。栈是LIFO(LastInFirstOut),所以正确的做法是:

print_string:
  push ax        \
  push bx  \     |
  ...      | BX  | AX
  pop  bx  /     |
  pop  ax        /
  ret

但第二个文件支持成为一个你好世界,但只会产生重复的笑脸。

根据我之前的回答,您已将 print_string 子例程放置在程序底部附近。这很好,除了这个特定的子程序将从实地址模式代码中调用,因此必须使用 16 位编码。遗憾的是,由于 [bits 32] 指令,NASM 在到达该子程序时仍将使用 32 位编码。
解决这个问题的两种方法:

  • 将这个 print_string 子例程移到 [bits 32] 行的正上方

  • 或将其保留在原处并使用明确的[bits 16] 进行标记

      [bits 16]
      print_string:
        push ax
        ...
    

这应该可以解决在进入保护模式之前打印垃圾字符的问题。请一步一步进行,并确保这部分工作正常,然后再尝试进入保护模式。

【讨论】:

  • 如果您可以单击上一个答案的接受按钮,那就太好了!至少如果您有兴趣为您的问题找到好的答案...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多