-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathshell.asm
More file actions
188 lines (158 loc) · 9.72 KB
/
Copy pathshell.asm
File metadata and controls
188 lines (158 loc) · 9.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
;==========================
; SHELL
;==========================
[bits 16] ; tell NASM to assemble 16-bit code
[org 0x8000] ; tell NASM the code is running at 0x0000_8000 address (shell)
%define BOOTSECTOR_SEGMENT 0x7c0 ; boot sector segment address used for far jumps to execute boot sector games
%define BOOTSECTOR_ADDR 0x7c00 ; physical memory address used to init stack base pointer
%define FILES_ADDR 0x7e00 ; physical memory address to load FILES at from sector 2
%define OFFSET 8 ; size of a filename
%define ENTER_KEY 0x1c ; ENTER scan code
%define BACKSPACE_KEY 0x0e ; BACKSPACE scan code
mov ax, 0 ; set ACCUMULATOR REGISTER to 0
mov ds, ax ; set DATA SEGMENT to 0
mov es, ax ; set EXTRA SEGMENT to 0
mov ss, ax ; set STACK SEGMENT to 0
mov bp, 0x7c00 ; set STACK BASE to 0x0000_7c00
mov sp, bp ; set STACK POINTER to 0x0000_7c00
mov ah, 0x00 ; BIOS code to set video mode
mov al, 0x03 ; 80 x 25 text mode
int 0x10 ; set video mode
mov si, intro ; point SOURCE INDEX register to intro variable's address
call print_string ; print intro to screen
; main OS loop
shell_loop:
mov si, user_prompt ; point SOURCE INDEX register to user_prompt variable's address
call print_string ; print user_prompt to screen
mov di, user_input ; point DESTINATION INDEX register to user_input variable's address
mov al, 0 ; AL is used by stosb instruction
times 20 stosb ; store zero at DI and then increment DI
mov di, user_input ; point DESTINATION INDEX register to user_input variable's address
.next_byte:
mov ah, 0x00 ; BIOS code to read key stroke from the keyboard
int 0x16 ; read a single keystroke from the keyboard
cmp ah, ENTER_KEY ; if ENTER key has been pressed...
je .search ; got to .search label
cmp ah, BACKSPACE_KEY ; if BACKSPACE key has been pressed...
je .erase_char ; ... erase char
stosb ; store key that has been pressed into user_input variable
mov ah, 0x0e ; BIOS code for char output
int 0x10 ; echo char that has been typedtyped
jmp .next_byte ; read next byte from the user
.erase_char:
mov ah, 0x03 ; BIOS code to get cursor position
int 0x10 ; get cursor position
cmp dl, 3 ; cursor too far to the left?
je .next_byte ; if so process next byte
mov ah, 0x0e ; BIOS code for char output
mov al, 8 ; ASCII code for '\b'
int 0x10 ; move cursor one step back
mov ah, 0x0e ; BIOS code for char output
mov al, 0 ; ASCII code for empty char
int 0x10 ; move cursor one step back
mov ah, 0x0e ; BIOS code for char output
mov al, 8 ; ASCII code for '\b'
int 0x10 ; move cursor one step back
mov al, 0 ; AL is used by stosb instruction
dec di, ; drop user input pointer one position back
stosb ; replace whatever is there with 0
dec di ; drop user input pointer one position back
jmp .next_byte ; process next byte
.search:
call search_file ; ... search the game by name
jmp shell_loop ; infinite shell loop
; search file procedure
search_file:
cmp byte [user_input], 0 ; check the first byte user has entered
je .return ; if nothing then return
mov bx, 0 ; file name list index
mov dl, 3 ; sector of the first executable on the USB flash drive
.next_game:
mov ax, [file_list + bx] ; AX points to the address of the 1st char of the current file name located in 'files.asm'
cmp ax, no_file ; if no more files left in the list
je .no_file_found ; go to no file found label
add bx, 2 ; point bx to the next filename
inc dl ; sync file name with a corresponding sector on the USB flash drive
call compare_strings ; compare user_input with the corresponding file name
cmp cl, 1 ; if user input matches file name then execute corresponding file
je execute ; execute the file name corresponding binary file
jmp .next_game ; process next file name
.no_file_found:
mov si, error_no_file ; point SI to no_file_found variable
call print_string ; print error message
ret ; return to main OS shell loop
.return: ret ; return to main OS shell loop
;---------------------------------------------------------------------------------------------------------
; DI => scasb compares value stored in DI which is 's' with 's' stored in AX register
; and then increments DI if DF is 0
; v
; memory address 1: |s|n|a|t|0| user input string
; memory address 2: |s|n|a|k|e|0| file name string
; ^
; SI => lodsb loads value stored at SI to AX and then increments SI if DF is 0
;---------------------------------------------------------------------------------------------------------
; procedure to compare two strings
compare_strings:
cld ; clear direction flag so that SI and DI gets incremented after SCASB/LODSB
mov di, user_input ; point DI to the target string
mov si, ax ; point SI to the source string
.next_byte:
lodsb ; init AX equals to the value of where SI is pointing at
scasb ; compare the value of where DI is poining at with the value stored in AX
jne .return_false ; return flase if chars do not match
cmp al, 0 ; if reached the zero terminating char...
je .return_true ; ... string match each other
jmp .next_byte ; process next byte
.return_true:
mov cl, 1
ret
.return_false:
mov cl, 0
ret
; procedure to execute boot sector game
execute:
mov ax, BOOTSECTOR_SEGMENT ; init the segment
mov es, ax ; init EXTRA SEGMENT register
mov bx, 0 ; init local offset within the segment
mov cl, dl ; sector 2 on USB flash drive contains shell binary executable
call read_sector ; read sector from USB flash drive
jmp BOOTSECTOR_SEGMENT:0x0000 ; jump to rhe shell executable and run it
; procedure to print a string
print_string:
cld ; clear direction flag
mov ah, 0x0e ; teletype output for 0x10 BIOS interrupt
mov bh, 0 ; page number
mov bl, 0x0F ; red foreground, silver background
.next_char: ; print next char
lodsb ; read next byte from SI register and then increment SI
cmp al, 0 ; match the zero terminating char of the string
je .return ; return if the string doesn't contain any chars anymore
int 0x10 ; print a single char with the specified color attribute
jmp .next_char ; repeat printing char until the string is fully printed
.return:
ret ; return from procedure
; procedure to read a single sector from USB flash drive
read_sector:
mov ah, 0x02 ; BIOS code to READ from storage device
mov al, 1 ; how many sectors to read
mov ch, 0 ; specify celinder
mov dh, 0 ; specify head
mov dl, 0x80 ; specify HDD code
int 0x13 ; read the sector from USB flash drive
jc .error ; if failed to read the sector handle the error
ret ; return from procedure
.error:
mov si, error_message ; point SOURCE INDEX register to error_message string's address
call print_string ; print error message
jmp $ ; stuck here forevevr (infinite loop)
; messages
error_message db 'Failed to read sector from USB!', 10, 13, 0
error_no_file db 10, 13, 'No file found!', 0
; variables
intro db '|===============================|',10,13,'|-------ARCADE OS (BETA)--------|',10,13,'| |',10,13,'| Type "list" to list the Games |', 10, 13,'|===============================|', 0
user_prompt db 10, 13, ' $ ', 0
user_input times 20 db 0
new_line db 10, 13
no_file dw 0
file_list dw FILES_ADDR, FILES_ADDR + OFFSET, FILES_ADDR + 2 * OFFSET, FILES_ADDR + 3 * OFFSET,FILES_ADDR + 4 * OFFSET, no_file
times 512 - ($ - $$) db 0 ; fill trailing zeros to get exactly 512 bytes long binary file