【问题标题】:adding assembly code erase displayed strings添加汇编代码擦除显示的字符串
【发布时间】:2018-04-08 09:19:12
【问题描述】:

我尝试编写我的迷你操作系统。我从其他项目中学习,所以我真的不知道我的代码对于引导加载程序和内核是否“正常”。我使用程序集 16 位 NASM,并将引导加载程序和内核作为 .bin 文件加载到软盘映像中。我用 qemu 运行操作系统。我发现添加更多代码行会擦除启动操作系统时出现的显示字符串。 例如,如果我启动操作系统并显示“欢迎使用我的操作系统!”,在添加一些代码行后,它会显示为“欢迎使用 m”(结尾消失)。

这是我的代码:

bootloader.asm

[bits 16]
[org 0x7c00]

                                ; Use the boot drive number passed to us by BIOS in register DL
start:
    xor ax,ax                   ; We want a segment of 0 for DS
    mov ds,ax                   ;     Set AX to appropriate segment value
    mov es,ax                   ; In this case we'll default to ES=DS
    mov bx,0x8000               ; Stack segment can be any usable memory

    mov ss,bx                   ; This places it with the top of the stack @ 0x80000.
    mov sp,ax                   ; Set SP=0 so the bottom of stack will be @ 0x8FFFF


    cld                         ; Set the direction flag to be positive direction

    mov si, welcome_msg
    call print_string

    mov si, kernel_load
    call print_string

    pushf
    stc

    mov ah,00h                  ; Reset Disk Drive
    int 13h

    read_sector:
        mov ax, 0x0
        mov es, ax              ; ES = 0
        mov bx, 0x1000          ; BX = 0x1000. ES:BX=0x0:0x1000 
                                ; ES:BX = starting address to read sector(s) into
        mov ah, 02              ; Int 13h/AH=2 = Read Sectors From Drive
        mov al, 01              ; Sectors to read = 1
        mov ch, 00              ; CH=Cylinder. Second sector of disk
                                ; is at Cylinder 0 not 1
        mov cl, 02              ; Sector to read = 2
        mov dh, 00              ; Head to read = 0
                                ; DL hasn't been destroyed by our bootloader code and still
                                ;     contains boot drive # passed to our bootloader by the BIOS
        int 13h                 ; Read Sectors From Drive

        jc error_kernel_load    ; error loading kernel
        popf
        jmp 0x0:0x1000          ; jmp to kernel offset
        cli                     ; Disable interrupts to circumvent bug on early 8088 CPUs
        hlt                     ; halts the central processing unit (CPU) until the next external interrupt

error_kernel_load:
        mov si, error_msg
        call print_string
        mov si, restart_msg
        call print_string
        mov ah,00               ; wait for key press
        int 16h
        xor ax,ax               
        int 19h                 ; reboot the computer

print_string:                   ; Routine: output string in SI to screen
        lodsb                   ; Get character from string
        or al,al
        jz exit
        mov ah,0x0e
        int 10h                 ; int 10h 'print char' function
        jmp print_string
exit:
        ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Messages to print
    welcome_msg db 'Welcome to Bootloader!!!',0x0D,0x0A,0
    kernel_load db 'Loading kernel....',0x0D,0x0A,0
    error_msg db 'Kernel.bin not found!',0x0D,0x0A,0
    restart_msg db 'Press any key to restart..',0

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


times 510-($-$$) db 0       ; Create padding to fill out to 510 bytes
dw      0xaa55              ; Magic number in the trailer of a boot secto

kernel.asm

[bits 16]
[org 0x1000]

section .data:
    cursor_col:     db     0                ; cursor column
    cursor_row:     db     0                ; cursor row
    line_col:       dw     0                ; line column
    line_row:       dw     0                ; line row

    color:          db     3Fh              ; background and forground color (at start set random the formal way > number+letter)

    mode:           db     0


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 byte [color], 3Fh
    call clear_screen                       ; clear the screen and color it

                                            ; VVV print "Minerald welcome" message VVV
    mov byte [cursor_col], 08               
    mov byte [cursor_row], 28
    call set_cursor                         ; print at the requested position of the screen
    mov si, welcome_string                  ; Put string position into SI
    call print_string                       ; Call our string-printing routine


                                            ; VVV print "Press Space" message VVV
    mov byte [cursor_col], 14
    mov byte [cursor_row], 26
    call set_cursor                         ; print at the requested position of the screen
    mov si, press_key_string                ; Put string position into SI
    call print_string                       ; Call our string-printing routine


    mov ah, 0h                              ; wait for key press
    int 16h                                                 

    mov byte [color], 1Fh
    call clear_screen                       ; clear the screen and color it


    mov byte [cursor_col], 2
    mov byte [cursor_row], 0
    call set_cursor                         ; print at the requested position of the screen
    mov si, basic_background                ; Put string position into SI
    call print_string   

    mov byte [cursor_col], 22
    mov byte [cursor_row], 0
    call set_cursor                         ; print at the requested position of the screen
    mov si, basic_background                ; Put string position into SI
    call print_string                       ; Call our string-printing routine


    mov ah, 0                               ; set display mode function.
    mov al, 13h                             ; mode 13h = 320x200 pixels, 256 colors.
    int 10h                                 ; set it!

    ;=================================      ; rectangles
    mov byte [line_col], 80
    mov byte [line_row], 165

    call print_rectangle                    ; print rectangle

    mov byte [line_col], 80
    mov byte [line_row], 135

    call print_rectangle                    ; print rectangle
    ;==================================


end:
    jmp $                                   ; Jump here - infinite loop!
    ;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;
clear_screen:
    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, byte [color]                    ; set background and foreground color
    int 10h
    ret
;;;;;;;;;;

;;;;;;;;;;
print_string:                               ; Routine: output string in SI to screen
    lodsb                                   ; Get character from string
    or al,al
    jz exit
    mov ah,0x0e                             ; int 10h 'print char' function
    int 10h
    jmp print_string
exit:
    ret

;;;;;;;;;;

;;;;;;;;;;
set_cursor:
    mov dh, byte [cursor_col]               ; cursor col 
    mov dl, byte [cursor_row]               ; cursor row
    mov ah, 02h                             ; move cursor to the right place
    xor bh, bh                              ; video page 0
    int 10h                                 ; call bios service
    ret
;;;;;;;;;;

;;;;;;;;;;
print_rectangle:
    %INCLUDE "print_rectangle.asm"
;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Messages to print
    welcome_string       db 'Welcome to  my OS!', 0
    press_key_string     db 'Press any key to continue...', 0
    enter_message_string db 'Enter your message below',0
    APM_ERROR_string     db 'APM Error...'
    basic_background     db '--------------------------------------------------------------------------------'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;END OF KERNEL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

这是负载命令:

nasm -f bin -o kernel.bin kernel.asm
nasm -f bin -o bootloader.bin bootloader.asm

dd if=bootloader.bin of=floppy.flp bs=512 seek=0 conv=notrunc 
dd if=kernel.bin of=floppy.flp bs=512 seek=1 conv=notrunc

qemu-system-i386 -fda floppy.flp

编辑:

来自消息被截断之前的 nasm 列表文件:

   300                                  ; Messages to print
   301 00000191 57656C636F6D652074-         welcome_string       db 'Welcome to my OS!', 0
   302 0000019A 6F204D696E6572616C-
   303 000001A3 644F532100         
   304 000001A8 507265737320616E79-         press_key_string     db 'Press any key to continue...', 0
   305 000001B1 206B657920746F2063-
   306 000001BA 6F6E74696E75652E2E-
   307 000001C3 2E00               
   308 000001C5 456E74657220796F75-         enter_message_string db 'Enter your message below',0
   309 000001CE 72206D657373616765-
   310 000001D7 2062656C6F7700     
   311 000001DE 41504D204572726F72-         APM_ERROR_string     db 'APM Error...'
   312 000001E7 2E2E2E             
   313 000001EA 2D2D2D2D2D2D2D2D2D-         basic_background     db '--------------------------------------------------------------------------------'

来自消息被截断后的 nasm 列表文件:

   332                                  ; Messages to print
   333 000001E8 57656C636F6D652074-         welcome_string       db 'Welcome to MineraldOS!', 0
   334 000001F1 6F204D696E6572616C-
   335 000001FA 644F532100         
   336 000001FF 507265737320616E79-         press_key_string     db 'Press any key to continue...', 0
   337 00000208 206B657920746F2063-
   338 00000211 6F6E74696E75652E2E-
   339 0000021A 2E00               
   340 0000021C 456E74657220796F75-         enter_message_string db 'Enter your message below',0
   341 00000225 72206D657373616765-
   342 0000022E 2062656C6F7700     
   343 00000235 41504D204572726F72-         APM_ERROR_string     db 'APM Error...'
   344 0000023E 2E2E2E             
   345 00000241 2D2D2D2D2D2D2D2D2D-         basic_background     db '--------------------------------------------------------------------------------'
   346 0000024A 2D2D2D2D2D2D2D2D2D-

【问题讨论】:

  • 你能在 NASM 列表文件中添加带有消息的行吗? (-l kernel.lst 选项并仅复制 welcome_string 周围的几行) - 查看它是如何编译的,以及它们放置在哪个偏移量处。
  • @Ped7g 我编辑了问题。
  • 这是来自显示字符串已被截断的版本,还是来自有效的版本?我有点担心你会越过 512B 扇区边界,但清单并没有暗示,最后一个 0x1EA 偏移量仍然在 512B 内,所以它可能是代码中的内容(我还没有阅读)。
  • 在代码中,可能与您的错误无关,但是您对int 10,0E service的使用不正确,您没有将BH设置为当前页面,在我看来可能有扇区读取仍然有一些价值,可能是0x10,这使得它可能会意外工作,但我不愿意深入挖掘粗心编写的代码,并且可能仅通过执行它并检查输出来“验证”。停止这样做,在调试器中单步执行每条指令,并验证指令的所有假设/效果,不要依赖输出。
  • 感谢您的宝贵时间。我还在上高中,在 [on windows] 之前我在汇编中编码,但显然我仍然不是 100% 掌握所有基础知识。最后一条评论是你可以使用“db 195”而不是“ret”,这对我来说是新的,而且很有趣。真的很有帮助,非常感谢:)

标签: assembly operating-system 16-bit


【解决方案1】:

回答你原来的问题:

那是因为你的内核变长了,而且它总共超过一个磁盘扇区大小,但你只将它的一个扇区(512 字节)加载到内存中,所以字符串的其余部分只保留在磁盘上,永远不会进入记忆。

还有其他几个问题(一些在我的 cmets 中提到),但这些与字符串截断并不真正相关,而且我没有心情+时间来查看您的所有bootloader+kernel 并修复你那里的所有错误,所以我会在这里停下来(答案)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-06
    • 1970-01-01
    相关资源
    最近更新 更多