我正在尝试使用 NASM 和 QEMU 在 16 位汇编中创建一个简单的命令行。到目前为止,一切正常,直到我再添加一根字符串。
当我添加另一个字符串时,程序不会显示应有的所有内容。
当我添加最后一个
msgHelpEcho
字符串时,它会显示提示而不是像这样的 ">"
" >"
,或者当我输入 help 时,它会正确显示前几个命令,但最后一个命令总是被切成两半或丢失,或转入空白处“ ”。
过去几天我一直在寻找原因,发现将字符串的声明移动到代码中的另一行会更改输出,但它仍然不正确。 提前致谢!这是代码:
org 0x8000 ; the program starts from 8000
bits 16 ; the program is 16-bit
; si - for read and write strings
; di - for comparing commands
section .text
global _start
_start:
call cls ; clear screen
; this is the start of the kernel
mov si, titleString ; print the title string
call printStr
mov si, newLine
call printStr
main:
mov si, prompt ; this is the char befor the UI
call printStr
; here the kernel asks for user input
mov di, readBuffer
call getInput
; here we split the input in to caommand and arguments
mov si, readBuffer
call splitCommand
; here are the commands
mov si, readBuffer
cmp byte [si], 0 ; to see if there is a blank line
je main
mov si, command
mov di, cmdclear
call cmpUI
jc cls
mov si, command ; this is the help command
mov di, cmdHelp
call cmpUI
jc .help
mov si, command ; this is for the echo command
mov di, cmdEcho
call cmpUI
jc .echo
mov si, command ; this is for the shutdown command
mov di, cmdShutdown
call cmpUI
jc .shutdown
mov si, badCmd ; if all command aren't triggered then print no such command
call printStr
jmp main
.shutdown:
; turn off the system
mov ax, 0x5307
mov bx, 0x0001
int 0x15
jmp .shutdown
.help:
mov si, msgHelp ; help text
call printStr
;mov si, msgHelpHelp ; -help
;call printStr
;mov si, msgHelpExit ; -shutdown
;call printStr
;mov si, msgHelpClear ; -clear
;call printStr
jmp main
.echo:
mov si, arguments
call printStr
mov si, newLine
call printStr
jmp main
jmp main ; infinite loop
printStr:
mov ah, 0x0e ; Move 0x0e in ah to use interupts
mov al, [si] ; Move the first char of the string in al
psloop:
int 0x10 ; 0x10 is interrupt for print
inc si ; incrementing the si stack index
mov al, [si] ; moving the new char from the string in the si stack to al
cmp al, 0 ; comparing al to 0
jne psloop ; is al is not 0 loop back
ret
ret
getInput:
xor cl, cl
.loop:
mov ah, 0x00 ; this is for the interrupt
int 0x16 ; this interrupt is for reading the next char
cmp al, 0x08 ; if backspace is pressed
je .backspace
cmp al, 0x0d ; if enter is pressed
je .done
cmp cl, 0x3f ; if 63 chars are entered
je .loop
mov ah, 0x0e ; when something is entered print it
int 0x10
stosb ; put the char in the buffer
inc cl
jmp .loop
.backspace:
cmp cl, 0 ; if it is the beginning of the string
je .loop
dec di
mov byte [di], 0 ; delete the char
dec cl ; decrement counter as well
mov ah, 0x0e
mov al, 0x08
int 0x10 ; backspace on the screen
mov al, ' '
int 0x10 ; blank char out
mov al, 0x08
int 0x10 ; backspace again
jmp .loop
.done:
mov al, 0 ; null the terminal
stosb
mov ah, 0x0e
mov al, 0x0d
int 0x10
mov al, 0x0a
int 0x10 ; new line
ret
cls:
pusha ; push the stack
mov al, 0x03 ; this is for the interrupt
mov ah, 0x00 ; this is also for the interrupt
int 0x10 ; this interrupt clears all the junk the BIOS prints
popa ; pop the stack
ret
cmpUI:
.loop:
mov al, [si] ; grab a byte from si
mov bl, [di] ; grab a byte from di
cmp al, bl
jne .notequal
cmp al, 0 ; are both bytes null
je .done
inc di
inc si
jmp .loop
.notequal:
clc ; not equal, clear the carry flag
ret
.done:
stc ; equal, set the carry flag
ret
splitCommand:
mov cx, 0
mov di, command
.find_space:
lodsb ; take a byte from si and put it in al
cmp al, ' '
je .found_space
stosb ; take a byte from al and put it in di
inc cx
test al, al
jnz .find_space
jmp .done
.found_space:
mov di, arguments
.copy_arguments:
lodsb
stosb
test al, al
jnz .copy_arguments
.done:
ret
section .data
; commands
cmdHelp db 'help', 0 ; this is for the help command
cmdShutdown db 'shutdown', 0 ; this is for shutting down the computer
cmdEcho db 'echo', 0 ; this is for the echo command
cmdclear db 'clear', 0 ; clear the screen
readBuffer times 64 db 0 ; the buffer for the read UI
prompt db '>', 0 ; this is the char before the read UI
titleString db 'Command line', 13, 10, 0 ; this is the string
; help texts
msgHelp db 'The available commands are:', 13, 10, 0 ; this is the message from the help command
msgHelpHelp db '-help - displays all the commands', 13, 10, 0
msgHelpExit db '-shutdown - shuts down the computer', 13, 10, 0
msgHelpClear db '-clear - clear the screen', 13, 10, 0
msgHelpEcho db '-echo - echos the text after it', 13, 10, 0
newLine db ' ', 13, 10, 0 ; new line
badCmd db 'No such command.', 13, 10, 0 ; when there is no such command
section .bss
command resb 16 ; buffer to store command
arguments resb 64 ; buffer to store arguments
这是我使用的引导加载程序:
ORG 0x7C00
BITS 16
main:
hlt
load_and_execute_kernel:
mov ah, 0x02
mov al, 1
mov ch, 0
mov dh, 0
mov dl, 0x80
mov bx, 0x8000
mov cx, 0x0002
int 0x13
jmp 0x8000 ;jump to entry point of kernel...
times 510-($-$$) db 0
dw 0AA55h
更改引导加载程序以加载另一个扇区并且它可以工作!
ORG 0x7C00
BITS 16
main:
hlt
load_and_execute_kernel:
mov ah, 0x02
mov al, 2
mov ch, 0
mov dh, 0
mov dl, 0x80
mov bx, 0x8000
mov cx, 0x0002
int 0x13
jmp 0x8000 ;jump to entry point of kernel...
times 510-($-$$) db 0
dw 0AA55h