问题
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