I'm trying to finish this program which forks a command line shell, however, it's not quite working properly. Anything stick out to you?
; nasm -f elf32 -g assn6.asm -o assn6.o
; ld -m elf_i386 assn6.o -o assn6
; A forked command shell written in nasm x86 assembly language
;
; --------------------
bits 32
global _start
input_buf_size equ 1024
section .bss
byte_buf resb 1
input_buf resb 1024 ; input lines will contain no more than 1024 characters
buflen resb 1024
section .data
prompt db "$ "
exit_typed db "exit", 10
cmd_not_found db ": command not found", 10
section .text
_start:
push ebp ; stack prologue
mov ebp, esp
setup_cl_prompt:
xor eax, eax ; clear eax
mov ebx, dword [byte_buf] ; store typed buffer into ebx
clear_cmd:
cmp eax, ebx ; have we gone through all characters yet?
jge clear_cmd_line ; if yes, display prompt
mov byte [input_buf + eax], 0 ; clear the buffer
inc eax ; evaluate next char
jmp clear_cmd ; continue
clear_cmd_line:
mov eax, 4 ; write syscall
mov ebx, 1 ; write to stdout
mov ecx, prompt ; chars to write
mov edx, 2 ; size_t= 2 chars (bytes) to write
int 0x80
cmd_line_input:
mov eax, 3 ; syscall read
mov ebx, 0 ; read from stdin (keyboard)
mov ecx, input_buf ; input_buf stores characters read from keyboard
mov edx, input_buf_size ; size_t (1024 bytes)
int 0x80
mov dword [byte_buf], eax ; eax returns # bytes read (characters typed by user): stored into byte_buf
cmp eax, 0 ; if nothing was typed, go back to prompt
je setup_cl_prompt
cmp eax, 1 ; if 1 byte read, must be return key
je setup_cl_prompt
cmp eax, 5 ; if 5 bytes read, could be "exit\n"
je user_exit
jmp back_to_shell
;return_check:
; cmp byte [input_buf], 10 ; is return?
; je setup_cl_prompt ; back to command line if yes
back_to_shell:
;mov eax, dword [byte_buf] ; restores number of bytes read into eax
xor ebx, ebx ; ebx used as counter
xor ecx, ecx ; so that ch can be used to store a character later for comparison
is_space_or_ret:
cmp ebx, eax ; if number of bytes read = counter, all characters have been evaluated, jump
je get_cmd_name ; XXXXXXXXXXXX JE TO JGE XXXXXXXXXXXXXX
mov ch, byte [input_buf + ebx] ; move [count] byte into ch
cmp byte ch, 0x20 ; is [count] byte a space?
je fix_char ; get rid of space if yes
cmp byte ch, 10 ; is [count] byte return key?
je fix_char ; null out return key if yes
inc ebx ; proceed to next byte in keyboard input
jmp is_space_or_ret
fix_char:
mov byte ch, 0
mov byte [input_buf + ebx], ch ; place null where space/ ret was (space/ ret = different commands)
inc ebx ; proceed to next byte in keyboard input
jmp is_space_or_ret
get_cmd_name:
mov esi, input_buf ; esi stores user typed buffer
sub eax, 2 ; subtract null and last character so that only command name can be evaluated
add esi, eax ; esi now points to the last character of the command (minus return and null)
find_cmd_name:
cmp eax, 0 ; test for no more chars left to examine
je cmd_name ; XXXXXXX JE TO JLE XXXXXXX now we have the name of command user typed
cmp byte [esi], 0 ; null?
je out_cmd_name
dec esi ; "next" character (pointing backwards)
dec eax ; decrease counter
jmp find_cmd_name
out_cmd_name:
inc esi ; move past null
push esi ; string pushed to stack
sub esi, 2 ; back to typed character before null
dec eax ; decrease counter
jmp find_cmd_name
cmd_name:
push esi ; command name typed by user pushed onto stack
cmd_fork:
mov eax, 2 ; fork syscall
int 0x80
cmp eax, 0 ; if 0, fork success, -1= error
jl fork_error
je child_process
jg parent_process ; pid of child process returned in parent
child_process:
mov eax, 11 ; execve syscall for executing the user typed command
mov ebx, input_buf ; what was typed (argv[])
mov ecx, esp ; put envp variables on stack
lea edx, [ebp + 16] ; start at first arg
int 0x80
jmp setup_cl_prompt ; XXXXXXXXXXXXXXXXXXXXXXXXXXX
fork_error:
mov eax, 4 ; write syscall for printing error to user
mov ebx, 1 ; print to stdout
mov ecx, input_buf ; print the user input first per program directions
mov edx, [byte_buf] ; size_t
int 0x80
mov eax, 4 ; write syscall
mov ebx, 1 ; write to screen
mov ecx, cmd_not_found ; generic error message
mov edx, 20 ; size_t of generic error message
int 0x80
jmp exit_shell
parent_process:
mov ebx, eax ; pid of child
mov eax, 7 ; wait syscall (so that parent can wait for child to execve)
mov ecx, buflen ; storage space for wait status
mov edx, 0 ; no options set
mov esp, ebp ; stack epilogue
jmp setup_cl_prompt
user_exit:
cld ; clear direction flag
mov ecx, 5 ; 5 bytes (characters) for "exit\n", count used for "rep"
mov edi, exit_typed
mov esi, input_buf ; to compare if "exit\n" has been typed by the user
repe cmpsb ; compare string bytes- are they both "exit\n" ? If yes --> exit
jne back_to_shell ; if "exit\n" not typed, we go back to shell
je exit_shell
exit_child:
mov esp, ebp ; stack epilogue
mov eax, 1 ; an extra sys exit to kill the child
int 0x80
exit_shell:
mov esp, ebp ; stack epilogue
mov eax, 1 ; syscall exit
int 0x80