【问题标题】:When I modify code the disk image becomes unbootable当我修改代码时,磁盘映像变得无法启动
【发布时间】:2018-12-15 19:03:06
【问题描述】:

我正在用汇编语言开发一个操作系统。更改代码时,输​​出文件不被视为可启动文件。

这是我的代码:

BITS 16

start:
    mov ax, 07C0h       ; Set up 4K stack space after this bootloader
    add ax, 288     ; (4096 + 512) / 16 bytes per paragraph
    mov ss, ax
    mov sp, 4096
    mov ax, 07C0h       ; Set data segment to where we're loaded
    mov ds, ax
    call cls
    MOV AH, 06h    ; Scroll up function
    XOR AL, AL     ; Clear entire screen
    XOR CX, CX     ; Upper left corner CH=row, CL=column
    MOV DX, 184FH  ; lower right corner DH=row, DL=column 
    MOV BH, 1Eh    ; YellowOnBlue
    INT 10H
    mov si, text_string ; Put string position into SI
    call print_string   ; Call our string-printing routine
push bx ;push registers
push cx
push dx
mov ah,0h
int 16h
       cmp al, '1'
       je reboot
       cmp al, '2'
       je shutdown
       cmp al, '3'
       je about
       cmp al, '4'
       je message
           cmp al, '5'
       je shutdown

       jmp $            ; Jump here - infinite loop!


    text_string db '|Main Menu| |Smile OS V1.2|',13,10,'1) Reboot',13,10,'2) Shutdown',13,10,'3) About',13,10,'4) Message',13,10,'5) System Halt',0
    about_string db '|About|',13,10,'Smile OS is a console based operating system in assembly.',13,10,'Press any key to go back!',0
    message_str db '|Message|',10,13,'Hello, World!',13,10,'Press any key to go back!',0

reboot:
mov ax, 0
int 19h

shutdown:
mov ax, 0x1000
mov ax, ss
mov sp, 0xf000
mov ax, 0x5307
mov bx, 0x0001
mov cx, 0x0003
int 0x15

message:
call cls
mov si, message_str ; Put string position into SI
call print_string   ; Call our string-printing routine
push bx ;push registers
push cx
push dx
mov ah,0h
int 16h     
je start

cls:
  pusha
  mov ah, 0x00
  mov al, 0x03  ; text mode 80x25 16 colours
  int 0x10
  popa
  ret

about:
call cls
mov si, about_string    ; Put string position into SI
call print_string   ; Call our string-printing routine
push bx ;push registers
push cx
push dx
mov ah,0h
int 16h 
je start

print_string:           ; Routine: output string in SI to screen
    mov ah, 0Eh     ; int 10h 'print char' function

.repeat:
    lodsb           ; Get character from string
    cmp al, 0
    je .done        ; If char is zero, end of string
    int 10h         ; Otherwise, print it
    jmp .repeat

.done:
    ret     

    times 512-($-$$) db 0   ; Pad remainder of boot sector with 0s
    dw 0xAA55       ; The standard PC boot signature

当我尝试恢复更改时,代码损坏了。

  • 我正在使用 Oracle VM VirtualBox 和最新版本的 NASM。
  • 我尝试重新启动计算机几次,但没有任何变化。
  • 我尝试安装旧版本的 NASM,但什么也没有。

我必须做些什么来修复这个引导加载程序?

【问题讨论】:

  • 我在你的问题中看不到从工作到不工作的变化。您似乎只展示了非工作版本。如果我们有一个从工作到损坏的差异,那么调试会容易得多。 (或者不是,因为 Michael 已经发现了一个 showstopper 错误,该错误显然会导致文件未被识别为有效的可启动 MBR。我的另一个猜测是你添加了太多东西,它不再适合 512 字节)
  • 程序是否仍适合 510 字节?

标签: assembly x86 virtualbox bootloader osdev


【解决方案1】:

你需要改变:

times 512-($-$$) db 0

到:

times 510-($-$$) db 0

您需要填充 510 字节,因此引导签名 0xaa55 是 512 字节引导扇区的最后 2 个字节。如果您不这样做,图像将不会被视为有效的引导扇区。您之前的问题提到使用命令:

nasm -f bin os.asm -o os.iso

您没有使用此命令生成 ISO(CD-ROM 映像)。要在 VirtualBox 中启动,我建议使用您的启动扇区创建一个 1.44MB 的软盘映像:

将文件组装成os.bin

nasm -f bin os.asm -o os.bin

在这一步之后检查文件os.bin正好 512 字节1。如果不是您在引导扇区中放置了过多的代码和数据,引导签名将位于错误的位置,VirtualBox 将拒绝将其识别为可引导设备。

创建一个名为os.img的空白1.44MB软盘映像:

dd if=/dev/zero of=os.img bs=1024 count=1440

os.bin复制到os.img的开头而不截断磁盘映像:

dd if=os.bin of=os.img conv=notrunc

在 VirtualBox 中将其设置为从 FLOPPY(不是 CD-ROM)启动并选择 os.img 文件作为启动映像。 VirtualBox 需要一个大小合适的软盘映像。

运行时您在此问题中显示的代码在我的 VirtualBox 中如下所示:


替代 TIMES 来捕捉重叠部分

如果你替换:

times 510-($-$$) db 0   ; Pad remainder of boot sector with 0s
dw 0xAA55               ; The standard PC boot signature

与:

section bootsig start=510
    dw 0xAA55           ; The standard PC boot signature

然后你会收到一个错误提示你的引导加载程序太大:

nasm:致命:部分 .text 和 bootsig 重叠!

这意味着bootsig 之前部分中的代码与引导签名部分重叠。如果发生这种情况,那么您将知道是时候自己读取磁盘扇区以将代码扩展到 512 字节引导扇区之外了。

如果使用ORG 0x7c00,那么start=510 必须是start=0x7c00+510

如果你依靠TIMES 告诉你有问题,它看起来像:

os.asm:###: 错误:TIMES 值 -### 为负数


1 如果文件os.bin 超过512 字节,那么您将需要使用BIOS 手动将更多磁盘扇区读入内存。从软盘读取磁盘可以通过INT 13h/AH=2h 完成。

【讨论】:

    猜你喜欢
    • 2019-11-03
    • 1970-01-01
    • 2018-03-08
    • 1970-01-01
    • 2013-01-03
    • 2018-02-21
    • 2021-10-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多