(assembly x86 real mode) Data gets “cut off” at the end of the program?

情到浓时终转凉″ 提交于 2019-12-12 15:06:04

问题


This is a follow-up from (nasm x86 real mode) How to write/read strings in boot-loaded sector?.

I'm working on a toy OS for x86 real mode in NASM. The 512B boot sector loads another sector with the rest of the code. The problem is that I seem to run out of space at the end of the program.

Here's the beginning of the source file:

;;; nasm -f bin -o boot.bin os.asm
;;; qemu-system-x86_64 boot.bin

    bits 16

    section boot, vstart=0x0000

    ;; Load next sector.
    ;; adapted from:
    ;; https://blog.benjojo.co.uk/post/interactive-x86-bootloader-tutorial
    mov ah, 0x02
    mov al, 1   
    mov ch, 0    
    mov cl, 2    
    mov dh, 0   
    mov bx, newsector 
    mov es, bx  
    xor bx, bx
    int 0x13
    jmp newsector:0

    newsector equ 0x0500

    times 510-($-$$) db 0
    db 0x55
    db 0xaa

    section os, vstart=0x0000
    mov ax, newsector
    mov ds, ax

And here's the end of the source file, where I store the data. There's a keymap to convert input according to the Dvorak keyboard layout. But the program seems to get "cut off" after fu.

    input times 16 db 0
    repl_prompt times 16 db 0

    dvorak db 1

dvorak_keymap:
    db "aa"
    db "nb"
    db "ic"
    db "hd"
    db "de"
    db "yf"
    db "ug"
    db "jh"
    db "gi"
    db "cj"
    db "vk"
    db "pl"
    db "mm"
    db "ln"
    db "so"
    db "rp"
    db "xq"
    db "or"
    db ";s"
    db "kt"
    db "fu"
    db ".v"     ; FIXME: gets cut off here
    db ",w"
    db "bx"
    db "ty"
    db "/z"
    db 0

So when you boot the OS, you can type keys a-u in Dvorak but not v-z. Furthermore, calling the program's print function on the dvorak_keymap string confirms that the string terminates after fu.

But more importantly, this indicates that I've run out of space in my program so I can't add any more data or code. I can't have hit the 1 MB memory limit because the source file is only 282 sloc.

I'm guessing it has something to do with how I load the sectors? I'm new to assembly and low-level programming so any help would be greatly appreciated.

source: https://github.com/jtherrmann/os/blob/master/os.asm

raw: https://raw.githubusercontent.com/jtherrmann/os/master/os.asm

Edit: Additionally, when I add more data/code higher up in the file, the keymap gets cut off earlier, and when I remove higher up data/code, the keymap gets cut off later or not at all. So I know that this has something to do with space limitations.


回答1:


Your code has multiple mistakes.

a) It doesn't set up a stack at a known location, and then loads data from disk at an address that might overwrite the stack (that might be at the same address).

b) It assumes that loading data from disk worked without checking if the BIOS returned an error.

c) It only loads one sector without any way to determine the actual size and "self-adjust"; so as the file grows it's going to be a continual maintenance chore. This is likely to be the reason why your data gets "cut off" (everything after the first 512 bytes are not loaded)

d) You use "newstart" before it's been defined, and then define "newstart equa 0x0500" after it's too late.

e) You assume all characters are printable. They aren't (cursor movement, function keys, ...)

Also note that your code to convert a character from QWERTY to Dvorak is incredibly inefficient (looping through all entries to find the right one instead of using the original character as an index into a table - e.g. like movzx eax,al, mov al,[table+eax]); and it currently won't work for a lot of cases (e.g. if the user presses "shift+a" or if they have capslock on).



来源:https://stackoverflow.com/questions/52463695/assembly-x86-real-mode-data-gets-cut-off-at-the-end-of-the-program

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!