linux - 加载引导加载程序的第二阶段和/或将控制权转移给它时出现问题

标签 linux assembly x86-16 bootloader bios

我的主引导记录代码:

;bit16                  ; 16bit by default
    org 0x7c00
    jmp short start
    nop
bsOEM   db "OS423 v.0.1"               ; OEM String

start:


;;cls
    mov ah,06h      ;Function 06h (scroll screen)
    mov al,0        ;Scroll all lines
    mov bh,0x0f     ;Attribute (lightgreen on blue) 
    mov ch,0        ;Upper left row is zero
    mov cl,0        ;Upper left column is zero
    mov dh,24       ;Lower left row is 24
    mov dl,79       ;Lower left column is 79
    int 10h         ;BIOS Interrupt 10h (video services)

;;print welcome msg
    mov ah,13h      ;Function 13h (display string), XT machine only
    mov al,1        ;Write mode is zero: cursor stay after last char
    mov bh,0        ;Use video page of zero
    mov bl,0x0f     ;Attribute (lightgreen on blue)
    mov cx,mlen     ;Character string length
    mov dh,0        ;Position on row 0
    mov dl,0        ;And column 0
    lea bp,[msg]    ;Load the offset address of string into BP, es:bp
                    ;Same as mov bp, msg 
    int 10h

;;load sector into memory & 5678h:1234h
    mov bx, 0x5678  ;segmented address
    mov es, bx      ;move segemented address to es
    mov bx,0x1234       ;base address to bx

    mov ah, 02      ;function read sectors
    mov al, 01      ;# of sectors to load
    mov ch, 00      ;track to read
    mov cl, 02      ;sector to read
    mov dh, 00      ;head to read
    mov dl, 00          ;drive number

    int 0x13            ;call interrupt 13 

    jmp 0x5678:0x1234       ;jump to memory address 


    int 20


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;variables;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

msg:  db 'Welcome to Pradox OS 0.1! Authored by Jiansong he', 10, 13, '$' 
mlen equ $-msg

padding times 510-($-$$) db 0       ;to make MBR 512 bytes
bootSig db 0x55, 0xaa       ;signature (optional)

用于 nasm 编译并将二进制文件放入我的 .img 软盘的终端命令:

line1: 定义一个软盘,名字为boot.img, block 大小512字节,一共2880字节

line2:使用nasm编译器,将mbr.asm文件编译成二进制格式,存放到名为mbr.bin的文件中(这是我的主引导记录)

line3: 在dt.bin 将dt.asm 编译成二进制

line4: 将mbr.bin的内容放入boot.img, block 大小512,共放入1个 block

line5: 将dt.bin 的内容放入boot.img, block 大小为512,物理扇区#2(逻辑扇区#1)

dd if=/dev/zero of=boot.img bs=512 count=2880 

nasm -f bin mbr.asm -o mbr.bin

nasm -f bin dt.asm -o dt.bin 

dd if=mbr.bin of=boot.img bs=512 count=1 conv=notrunc

dd if=dt.bin of=boot.img bs=512 seek=1 count=1 conv=notrunc 

dt.asm 中的代码:

[BITS 16]               ;Set code generation to 16 bit mode

ORG 0x5647:0x1234       ;set addressing to begin at 579b4H

startdt:
  ;call cls ;call routine to clear screen
  ;call dspmsg  ;call routine to display message

  call date
  call cvtmo
  call cvtday
  call cvtcent
  call cvtyear
  call dspdate

  call time
  call cvthrs
  call cvtmin
  call cvtsec
  call dsptime

  int 20h ;halt operation (VERY IMPORTANT!!!)


cls:             
  mov ah,06h    ;function 06h (Scroll Screen)
  mov al,0  ;scroll all lines
  mov bh,0x0f   ;Attribute (bright white on blue)
  mov ch,0  ;Upper left row is zero
  mov cl,0  ;Upper left column is zero
  mov dh,24 ;Lower left row is 24
  mov dl,79 ;Lower left column is 79
  int 10H   ;BIOS Interrupt 10h (video services)
  ret


dspmsg: 
  mov ah,13h    ;function 13h (Display String)
  mov al,1  ;Write mode is zero
  mov bh,0  ;Use video page of zero
  mov bl,0x0a   ;Attribute (bright white on bright blue)
  mov cx,mlen2  ;Character length
  mov dh,0  ;position on row 0
  mov dl,0  ;and column 0
  lea bp,[welcom]   ;load the offset address of string into BP

  int 10H
  ret

welcom: db 'jiansong Hes first Operating System :D',10,13,'$'
mlen2 equ $-welcom;

date:
;Get date from the system
mov ah,04h   ;function 04h (get RTC date)
int 1Ah     ;BIOS Interrupt 1Ah (Read Real Time Clock)
ret

;CH - Century
;CL - Year
;DH - Month
;DL - Day

cvtmo:
;Converts the system date from BCD to ASCII
mov bh,dh ;copy contents of month (dh) to bh
shr bh,1
shr bh,1
shr bh,1
shr bh,1
add bh,30h ;add 30h to convert to ascii
mov [dtfld],bh
mov bh,dh
and bh,0fh
add bh,30h
mov [dtfld + 1],bh
ret

cvtday:
mov bh,dl ;copy contents of day (dl) to bh
shr bh,1
shr bh,1
shr bh,1
shr bh,1
add bh,30h ;add 30h to convert to ascii
mov [dtfld + 3],bh
mov bh,dl
and bh,0fh
add bh,30h
mov [dtfld + 4],bh
ret

cvtcent:
mov bh,ch ;copy contents of century (ch) to bh
shr bh,1
shr bh,1
shr bh,1
shr bh,1
add bh,30h ;add 30h to convert to ascii
mov [dtfld + 6],bh
mov bh,ch
and bh,0fh
add bh,30h
mov [dtfld + 7],bh
ret

cvtyear:
mov bh,cl ;copy contents of year (cl) to bh
shr bh,1
shr bh,1
shr bh,1
shr bh,1
add bh,30h ;add 30h to convert to ascii
mov [dtfld + 8],bh
mov bh,cl
and bh,0fh
add bh,30h
mov [dtfld + 9],bh
ret

dtfld: db '00/00/0000'

dspdate:
;Display the system date
mov ah,13h ;function 13h (Display String)
mov al,0 ;Write mode is zero
mov bh,0 ;Use video page of zero
mov bl,0x0f ;Attribute
mov cx,10 ;Character string is 10 long
mov dh,4 ;position on row 4
mov dl,0 ;and column 28
push ds ;put ds register on stack
pop es ;pop it into es register
lea bp,[dtfld] ;load the offset address of string into BP
int 10H
ret

time:
;Get time from the system
mov ah,02h
int 1Ah
ret

;CH - Hours
;CL - Minutes
;DH - Seconds

cvthrs:
;Converts the system time from BCD to ASCII
mov bh,ch ;copy contents of hours (ch) to bh
shr bh,1
shr bh,1
shr bh,1
shr bh,1
add bh,30h ;add 30h to convert to ascii
mov [tmfld],bh
mov bh,ch
and bh,0fh
add bh,30h
mov [tmfld + 1],bh
ret

cvtmin:
mov bh,cl ;copy contents of minutes (cl) to bh
shr bh,1
shr bh,1
shr bh,1
shr bh,1
add bh,30h ;add 30h to convert to ascii
mov [tmfld + 3],bh
mov bh,cl
and bh,0fh
add bh,30h
mov [tmfld + 4],bh
ret

cvtsec:
mov bh,dh ;copy contents of seconds (dh) to bh
shr bh,1
shr bh,1
shr bh,1
shr bh,1
add bh,30h ;add 30h to convert to ascii
mov [tmfld + 6],bh
mov bh,dh
and bh,0fh
add bh,30h
mov [tmfld + 7],bh
ret

tmfld: db '00:00:00'

dsptime:
;Display the system time
mov ah,13h ;function 13h (Display String)
mov al,0 ;Write mode is zero
mov bh,0 ;Use video page of zero
mov bl,0x0f;Attribute
mov cx,8 ;Character string is 8 long
mov dh,5 ;position on row 5
mov dl,0;and column 0
push ds ;put ds register on stack
pop es ;pop it into es register
lea bp,[tmfld] ;load the offset address of string into BP
int 10H
ret

int 20H

我的测试环境是 dosbox,我可以在屏幕上成功显示欢迎消息,但无法将另一个扇区加载到从 0x5647:0x1234 开始的内存中 谢谢

最佳答案

足够简单。

您不能只使用 OEM 字符串启动引导扇区!
你必须跳过这个文本到真正的起点。
要么使用:

  • 3 字节近跳转
  • 一个 2 字节的短跳转,后跟一个 nop 指令。

mov ch, 01      ;track to read
mov cl, 02      ;sector to read
mov dh, 01      ;head to read

如果要读取驱动器的第 2 个扇区,则需要指定 Cylinder=0、Head=0 和 Sector=2

mov ch, 0      ;track to read
mov cl, 2      ;sector to read
mov dh, 0      ;head to read

您的引导消息可能不会显示,因为您没有设置 ES 段寄存器。鉴于 org 0x7C00,您需要设置 ES=0。您不能相信 BIOS 会为您执行此操作。


您可能希望从程序中删除 int 20 指令。它帮不了你。


与其使用 mov dl, 0 指定要加载的磁盘,不如使用引导扇区时获得的 DL 寄存器的内容首先由 BIOS 调用。 像 DOSBOX 这样的模拟器可能会在这里使用一些特定的值!

关于linux - 加载引导加载程序的第二阶段和/或将控制权转移给它时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41795817/

相关文章:

c - 当进程 fork 时,共享库 .so 是否仍在地址空间中?构造函数会再次执行吗?

linux - 交叉编译 node.js 到 MIPS 24Kc V5.0

linux - 如何在 Vim 中添加自定义模板?

python - 了解 python subprocess.check_output 的第一个参数和 shell=True

c++ - 为什么这段代码在实际的 BCM2837 (pi 3) 上运行时会挂起,但在 qemu 上运行良好

c - 以下内联汇编代码有什么问题?

assembly - 访问树莓派GPIO地址时出现段错误

assembly - mov bx,ax 和 mov bh,ah 之间的速度有区别吗?

assembly - BIOS 连续两次从不同端口读取同一寄存器

assembly - 为什么汇编语言运算时要在字符串后面加-2?