I want to make a small operating system in 16 bit assembly. In this code I'm creating a sort of 'terminal' where I take the user input and if the input is shutdown then start the function to shut everything down otherwise nothing happens and the loop resumes (for now, later I'll create other functions so if the command is not 'shutdown' then other checks will start to see if it's another command)
the code:
bits 16
section .kernel
global _start_kernel
_start_kernel:
mov ax, 0x3
int 10h
commandLoop:
mov si, user
call print
mov di, input_string
call input
mov si, input_string
call print
ifCommandShutdown:
cld
mov si, C_shutdown
mov di, input_string
mov cx, CL_shutdown
cmpsb
jz thenCommandShutdown
elseCommandShutdown:
call newLine
jmp commandLoop
thenCommandShutdown:
call shutdown
exit:
cli
hlt
%include "lib/console.asm"
%include "lib/system.asm"
user: db "user >> ", 0
input_string:
;- Commands Variables ------------------------------+
; |
C_shutdown: db "shutdown", 0 ; |
C_reboot: db "reboot" , 0 ; |
; |
CL_shutdown: db $ - C_shutdown ; |
CL_reboot: db $ - C_reboot ; |
; |
;---------------------------------------------------+
times 512-($-$$) db 0
console.asm:
print:
mov ah, 0x0e
characterLoop:
lodsb
or al, al
jz break
int 10h
jmp characterLoop
break:
ret
input:
mov ah, 0x0
int 16h
ifKeyIsEnter:
cmp al, 0x0D
jz enterIsPressed
elseEnterKey:
stosb
mov ah, 0x0e
int 10h
jmp input
enterIsPressed:
mov al, 0x0
stosb
call newLine
ret
newLine:
mov ah, 0x0e
mov al, 13
int 10h
mov al, 10
int 10h
ret
system.asm:
shutdown:
mov ax, 0x1000
mov ax, ss
mov sp, 0xf000
mov ax, 0x5307
mov bx, 0x0001
mov cx, 0x0003
int 0x15
There isn't errors when I compile but in qemu it always shutdown
cmps
returns always 0
Seeing how you laid out memory (forgetting to allocate room for the input):
input_string: C_shutdown: db "shutdown", 0
the input just overwrites the very text that you will be comparing to. Obviously the one-character compare cmpsb
then will always find a match.
Since it is the full word 'shutdown' that you want to verify and seeing your code:
cld mov si, C_shutdown mov di, input_string mov cx, CL_shutdown cmpsb
where you try to setup a count in CX, you should prepend the repe
(RepeatWhileEqual) prefix to the cmpsb
instruction.
Currently loading the count is wrong in that you load it with the address of the byte-sized variable CL_shutdown, where you need the actual contents of that variable. But it would be better to define these lengths as equates:
user: db "user >> ", 0
input_string: times 20 db 0
C_shutdown: db "shutdown", 0
CL_shutdown: equ $ - C_shutdown
C_reboot: db "reboot" , 0
CL_reboot: equ $ - C_reboot
The code to compare then becomes (assuming DS and ES have been setup correctly and equal to each other):
cld
mov si, C_shutdown ; DS:SI
mov di, input_string ; ES:DI
mov cx, CL_shutdown
repe cmpsb
jz thenCommandShutdown
shutdown: mov ax, 0x1000 mov ax, ss mov sp, 0xf000
An additional error is in shutdown. The mov ax, 0x1000
mov ax, ss
instructions make no sense (loading AX twice). This should read:
mov ax, 0x1000
mov ss, ax
mov sp, 0xF000