-
Notifications
You must be signed in to change notification settings - Fork 0
/
preboot.asm
209 lines (159 loc) · 4.01 KB
/
preboot.asm
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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
[org 0x7e00]
[cpu 8086]
[bits 16]
call cls
call sleep
mov si, GREET
call print
mov bx, 0 ; инициализируем bx как индекс для хранения ввода
jmp short get_input
; ------
get_input:
mov si, ARROW
call print
call input_processing
jmp get_input
input_processing:
mov ah, 0x00 ; параметр для 16h
int 0x16
cmp al, 0x0d ; Enter
je check_input
cmp al, 0x8 ; Backspace
je backspace
cmp al, 0x3 ; Ctrl+C
je halt
mov ah, 0x0e ; В противном случае выводим символ на печать
int 0x10
mov [INPUT+bx], al ; Вписываем символ в буфер ввода
add bx, 1 ; Увеличиваем индекс
cmp bx, 64 ; Чекаем переполнение
je check_input
jmp input_processing
check_input:
add bx, 1 ; Нужно в конец буфера вкинуть \0, чтобы получилась строка
mov byte [INPUT+bx], 0
mov si, NL ; Переход на новую строку в консоли
call print
mov bx, INPUT
; Блок halt
mov si, HALT_CMD
call cmp_si_bx
cmp cx, 1
je halt
; Блок help
mov si, HELP_CMD
call cmp_si_bx
cmp cx, 1
je help_matched
; Блок boot
mov si, BOOT_CMD
call cmp_si_bx
cmp cx, 1
je boot_matched
; Команда не найдена
jmp no_match
cmp_si_bx:
mov ah, [bx] ; мы не можем сравнить два байта напрямую, поэтому используем ah в качестве временного хранилища
cmp [si], ah ; теперь можем
jne not_equal
cmp byte [si], 0
je zero_reached
add si, 1 ; двигаемся по si дальше, если не добрались до \0
add bx, 1 ; двигаемся по bx дальше
jmp cmp_si_bx
zero_reached:
cmp byte [bx], 0
jne not_equal
mov cx, 1
ret
not_equal:
mov cx, 0
ret
backspace:
cmp bx, 0 ; возвращаемся назад, если стирать нечего
je input_processing
mov ah, 0x0e
int 0x10
mov al, ' ' ; печатаем пробел, чтобы стереть символ
int 0x10
mov al, 0x8 ; не даём каретке вернуться назад
int 0x10
sub bx, 1 ; уменьшаем индекс
mov byte [INPUT+bx], 0 ; срезаем введенные данные
jmp input_processing ; прыгаем назад
halt:
mov si, GOODBYE
call print
call sleep
mov ax, 0x5307 ; управление питанием
mov bx, 0x0001 ; всех устройств
mov cx, 0x0003 ; выключить
int 0x15
help_matched:
mov si, HELP_MSG
call print
jmp clean
boot_matched:
call cls
call sleep
int 0x18
no_match:
mov si, WRONG_CMD
call print
jmp clean
clean:
cmp bx, 0
je break
sub bx, 1
mov byte [INPUT+bx], 0
jmp clean
print:
mov al, [si]
cmp al, 0
je break
mov ah, 0x0e
int 0x10
add si, 1
jmp print
cls:
mov ah, 0x00 ; очистка экрана
mov al, 0x03
int 0x10
mov ah, 0x09 ; покрас экрана
mov cx, 0x1000
mov al, 0x20 ; зелёный на чёрном (https://en.wikipedia.org/wiki/BIOS_color_attributes)
mov bl, 0x02
int 0x10
ret
break:
ret
sleep:
mov cx, 0x0F
mov dx, 0x4240
mov ah, 0x86
int 0x15
ret
ARROW:
db '$> ', 0
GREET:
db "Type '?' for commands", 0x0d, 0x0a, 0x0a, 0
WRONG_CMD:
db 'Unknown command', 0x0d, 0x0a, 0
HELP_MSG:
db 'Known commands: boot, halt', 0x0d, 0x0a, 0
HELP_CMD:
db '?', 0
BOOT_CMD:
db 'boot', 0
HALT_CMD:
db 'halt', 0
GOODBYE:
db 0x0d, 0x0a, 0x0d, 0x0a, 'Process halted', 0x0d, 0x0a, 0
NL:
db 0x0d, 0x0a, 0
INPUT:
times 64 db 0
%assign used_mem ($-$$)
%assign usable_mem 512
%warning [used_mem/usable_mem] bytes used
times 512-($-$$) db 0