-
Notifications
You must be signed in to change notification settings - Fork 9
/
kernel.asm
664 lines (580 loc) · 11.1 KB
/
kernel.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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
BITS 16
[global _start]
[extern main]
[global RunNum]
[global UserID]
[global INT09H_FLAG]
;16k = 0x4000
;4M = 0x4 0 0000
MaxRunNum equ 128
MSG_SEGMENT equ 4000h
SCREEN_SEGMENT equ MSG_SEGMENT + 100h
PCB_SEGMENT equ SCREEN_SEGMENT + (80 * 25 * 2 / 16) * 4
PROG_SEGMENT equ PCB_SEGMENT + (MaxRunNum * PCBSize / 16)
UserProgramOffset equ 100h
UpdateTimes equ 20
;写入中断向量表
%macro WriteIVT 2
mov ax,%1
mov bx,4
mul bx
mov si,ax
mov ax,%2
mov [cs:si],ax ; offset
mov ax,cs
mov [cs:si + 2],ax
%endmacro
;Init
mov ax,cs
mov ds,ax
mov ax, 0
mov ss, ax
mov sp, 7c00h
mov ax, [cs:09h * 4]
mov word [INT09HORG], ax
mov ax, [cs:09h * 4 + 2]
mov word [INT09HORG + 2], ax
WriteIVT 08h,WKCNINTTimer ; Timer Interupt
WriteIVT 09h,WKCNINTKeyBoard
WriteIVT 20h,WKCNINT20H ; 进程退出(为了简单, 这个中断只有一个功能)
WriteIVT 21h,WKCNINT21H ; 进程功能
WriteIVT 22h,WKCNINT22H ; 进程通信
_start:
mov ax, PCB_SEGMENT
mov es, ax
mov al, 1
mov byte [es:_STATE_OFFSET], al; 设置Shell为运行态
;SetTimer
mov al,34h
out 43h,al ; write control word
mov ax,1193182/UpdateTimes ;X times / seconds
out 40h,al
mov al,ah
out 40h,al
mov ax,cs
mov ds,ax
mov ss,ax
mov es,ax
sti
jmp main
%macro SaveReg 1
mov ax, %1
mov [es:(bx + _%1_OFFSET)], ax
%endmacro
%macro LoadReg 1
mov ax, [es:(bx + _%1_OFFSET)]
mov %1, ax
%endmacro
;键盘中断
WKCNINTKeyBoard:
push ax
mov al,1
xor byte [cs:INT09H_FLAG], al
;sti
pushf
call far [cs:INT09HORG]
pop ax
iret
WKCNINT20H:
push es
push dx
push bx
push ax
;切换到ShellMode
mov ax, [cs:RunID]
mov bx, PCBSize
mul bx
mov bx, ax
mov ax, PCB_SEGMENT
mov es, ax
mov byte[es:(bx + _STATE_OFFSET)], 4 ; Dead
pop ax
pop bx
pop dx
pop es
iret
;注意, 如果这个放在代码段, 会导致被当成代码运行:-(
INT21HJMPLIST:
dw TabShellMode, TabProgState, GetRunID, RETN_PCB_S, RETN_PROG_S, RETN_MSG_S, RETN_MAXRUNNUM
dw STOP_CLOCK, START_CLOCK, INC_RUNNUM, RETN_RUNNUM, RETN_SCREEN_S
WKCNINT21H:
;21H中断
;AH = 00h, 切换ShellMode到al状态
;AH = 01h, 切换进程状态到al
;AH = 02h, 得到当前进程ID
;AH = 03h, 返回PCB_SEGMENT
;AH = 04h, 返回PROG_SEGMENT
;AH = 05h, 返回MSG_SEGMENT
;AH = 06h, 返回MaxRunNum
;AH = 07h, 停止时钟
;AH = 08h, 开启时钟
;AH = 09h, ++RunNum
;AH = 0Ah, 返回RunNum
;AH = 0Bh, 返回SCREEN_SEGMENT
push dx
push cx
push bx
;判断是否有效
;cmp ah, 0x09
;ja INT21HEND
xor bx, bx
mov bl, ah
shl bx, 1
jmp word[cs:(INT21HJMPLIST + bx)]
;AH = 00h
TabShellMode:
nop
jmp INT21HEND
;AH = 01h
TabProgState:
mov dl, al
mov ax, [cs:RunID]
mov bx, PCBSize
mul bx
mov bx, ax
mov ax, PCB_SEGMENT
push es
mov es, ax
mov byte[es:(bx + _STATE_OFFSET)], dl
pop es
jmp INT21HEND
;AH = 02h
GetRunID:
mov ax, [cs:RunID]
jmp INT21HEND
RETN_PCB_S:
mov ax, PCB_SEGMENT
jmp INT21HEND
RETN_PROG_S:
mov ax, PROG_SEGMENT
jmp INT21HEND
RETN_MSG_S:
mov ax, MSG_SEGMENT
jmp INT21HEND
RETN_SCREEN_S:
mov ax, SCREEN_SEGMENT
jmp INT21HEND
RETN_MAXRUNNUM:
mov ax, MaxRunNum
jmp INT21HEND
STOP_CLOCK:
mov byte[cs:CLOCKON],0
jmp INT21HEND
START_CLOCK:
mov byte[cs:CLOCKON],1
jmp INT21HEND
INC_RUNNUM:
inc word[cs:RunNum]
jmp INT21HEND
RETN_RUNNUM:
mov ax, word[cs:RunNum]
jmp INT21HEND
INT21HEND:
pop bx
pop cx
pop dx
iret
INT22HJMPLIST:
dw MSG_READ, MSG_WRITE, SET_MSG_V,RESET_MSG,CLOSE_MSG,INT22HEND
WKCNINT22H:
;22H进程, 进程通信
;ah = 00h 读
;ah = 01h 写
;ah = 02h 信号量设置(bh=0, 清零; bh=1, 加1; bh=2, 减1; bh=3, 设置为bl值)
;ah = 03h 设置端口
;ah = 04h 关闭端口
;ah = 05h 只返回信号量
;al = 端口值
;基地址bx, 缓存大小cx, 段地址dx
;返回信号量(ax)
;信号描述 大小
;是否开启 byte
;信号量 byte
;大小 word
;偏移量 word
;段地址 word
;
;总大小 8
MSG_OPENED_OFF equ 0
MSG_SIG_OFF equ 1
MSG_SIZE_OFF equ 2
MSG_OFFSET_OFF equ 4
MSG_SEG_OFF equ 6
push dx
push cx
push bx
push es
push ds
push si
push di
mov es, dx; es = 目标段地址
mov di, bx
;[es:di] = 目标量
mov bl, ah; bl 记录功能号
mov ah, 8
mul ah
;ax = 信号偏移量
mov si, ax
mov ax, MSG_SEGMENT
mov ds, ax
;[ds:si] = 信号量
cmp bl, 0x05
ja INT22HEND
mov bh, 0
shl bx, 1
jmp word[cs:(INT22HJMPLIST + bx)]
%macro INIT_MSG_RW 1
cmp byte[ds:si + MSG_OPENED_OFF], 0
je INT22HEND
cmp cx, word[ds:si + MSG_SIZE_OFF]
jbe NOT_OVERFLOW_%1
mov cx, word[ds:si + MSG_SIZE_OFF]
NOT_OVERFLOW_%1:
mov ax, [ds:si + MSG_SEG_OFF]
mov bx, [ds:si + MSG_OFFSET_OFF]
cld
%endmacro
MSG_READ:
INIT_MSG_RW 0
mov ds, ax
mov si, bx
MSG_READ_LOOP:
movsb
loop MSG_READ_LOOP
jmp INT22HEND
MSG_WRITE:
INIT_MSG_RW 1
mov dx, es
mov es, ax
mov ds, dx
mov si, di
mov di, bx
MSG_WRITE_LOOP:
movsb
loop MSG_WRITE_LOOP
mov dx, di
mov si, dx
mov dx, es
mov ds, dx
jmp INT22HEND
SET_MSG_V:
cmp byte[ds:si + MSG_OPENED_OFF], 0
je INT22HEND
;信号量设置(bh=0, 清零; bh=1, 加1; bh=2, 减1; bh=3, 设置为bl值)
mov bx, di
cmp bh, 0
je SET_MSG_V_CLEAR
cmp bh, 1
je SET_MSG_V_ADD
cmp bh, 2
je SET_MSG_V_DEC
cmp bh, 3
je SET_MSG_V_NUM
SET_MSG_V_CLEAR:
mov byte[ds:si+MSG_SIG_OFF],0
jmp INT22HEND
SET_MSG_V_ADD:
inc byte[ds:si+MSG_SIG_OFF]
jmp INT22HEND
SET_MSG_V_DEC:
dec byte[ds:si+MSG_SIG_OFF]
jmp INT22HEND
SET_MSG_V_NUM:
mov byte[ds:si+MSG_SIG_OFF],bl
jmp INT22HEND
RESET_MSG:
mov ax, 0x0001
mov word[ds:si], ax
mov word[ds:si + MSG_SIZE_OFF], cx
mov word[ds:si + MSG_OFFSET_OFF], di
mov ax, es
mov word[ds:si + MSG_SEG_OFF], ax
jmp INT22HEND
CLOSE_MSG:
xor al, al
mov byte[ds:si], al
jmp INT22HEND
INT22HEND:
;设置信号量
mov al, byte[ds:si + MSG_SIG_OFF]
pop di
pop si
pop ds
pop es
pop bx
pop cx
pop dx
iret
WKCNINTTimer:
;cli
;Save current Progress
;System Stack: *\flags\cs\ip
push ds
;System Stack: *\flags\cs\ip\ds(old)
push cs
;System Stack: *\flags\cs\ip\ds(old)\cs(kernel)
pop ds
;ds = data segment(kernel)
;System Stack: *\flags\cs\ip\ds(old)
mov [ds:AX_SAVE], ax
mov [ds:BX_SAVE], bx
mov [ds:CX_SAVE], cx
mov [ds:DX_SAVE], dx
mov ax, word[ds:RunID]
;Must have a progress, it is Shell :-)
;ES,DS,DI,SI,BP,SP,BX,DX,CX,AX,SS,IP,CS,FLAGS
mov bx,PCBSize
mul bx
;add ax, Processes; current process PCB
mov bx,ax
push ds
mov ax, PCB_SEGMENT
mov ds, ax
mov ax, es
mov [bx + _ES_OFFSET], ax
pop ds
mov ax, PCB_SEGMENT
mov es, ax
;SaveReg ES
SaveReg DI
SaveReg SI
SaveReg BP
pop word[es:(bx + _DS_OFFSET)] ;System Stack: *\flags\cs\ip\
nop; 如果不加这句,会丢失下面一条pop语句,奇怪的bug!
pop word[es:(bx + _IP_OFFSET)]
pop word[es:(bx + _CS_OFFSET)]
pop word[es:(bx + _FLAGS_OFFSET)]
;System Stack: *
SaveReg SP
mov ax, [ds:DX_SAVE]
mov [es:(bx + _DX_OFFSET)], ax
mov ax, [ds:CX_SAVE]
mov [es:(bx + _CX_OFFSET)], ax
mov ax, [ds:BX_SAVE]
mov [es:(bx + _BX_OFFSET)], ax
mov ax, ss
mov [es:(bx + _SS_OFFSET)], ax
mov ax, [ds:AX_SAVE]
mov [es:(bx + _AX_OFFSET)], ax
;All Saved!
;Run Next Program!
;进程调度
;ax 是将要运行的进程id
;可用寄存器, ax,bx
;运行用户程序
mov ax, word [ds:RunID]
mov cx, PCBSize
cmp byte [ds:CLOCKON], 1
jne GoodUserProg ; 不等于1, 说明切换关闭
;假如不是Running态, 不能继续运行
cmp byte [es:(bx + _STATE_OFFSET)], 1
jne FindUserProg
mov dl, byte [es:(bx + _UID_OFFSET)]
cmp dl, byte [ds:UserID]
jne FindUserProg
mov dl, byte [ds:PRIORITY_COUNT]
inc byte [ds:PRIORITY_COUNT]
;bx 还是之前程序的PCB偏移
cmp dl, byte [es:(bx + _PRIORITY_OFFSET)]
; <= 不高于,不进行进程切换
jna GoodUserProg
mov byte [ds:PRIORITY_COUNT], 0
FindUserProg:
inc ax
cmp ax, MaxRunNum
jb MayExUserProg
; 越界了
mov ax, 0
jmp GoodUserProg
;可能是要执行的用户程序
MayExUserProg:
push ax
mul cx
mov si, ax
pop ax
xor dx, dx
; 判断是否当前用户
mov dl, byte [es:(si + _UID_OFFSET)]
cmp byte [cs:UserID], dl
jne FindUserProg
;判断状态
mov dl, byte [es:(si + _STATE_OFFSET)]
shl dx, 1
mov di, dx
jmp word [cs:(ProgState + di)]
ProgState:
;EMPTY, RUNNING, SUSPEND, READY, DEAD, BLOCKED
dw FindUserProg, GoodUserProg, FindUserProg, ReadyState, DeadState, FindUserProg
ReadyState:
mov byte [es:(si + _STATE_OFFSET)], 1; Ready -> Running
jmp GoodUserProg
DeadState:
;Dead
cmp byte [es:(si + _KIND_OFFSET)], 2; 若等于则为线程
jne KillCommonProg
;线程终结处理
jmp FindUserProg ; 暂时处理方法为: 由主线程统一处理
%macro ReleaseProg 0
mov byte[cs:CLOCKON],0
push cx
push bx
push ax
;释放进程所占内存
mov ax, 0
mov bx, word [es:(si + _SEG_OFFSET)]
mov cx, word [es:(si + _SSIZE_OFFSET)]
sti
int 23h
;清除信号量
mov ah, 05h
mov al, byte [es:(si + _ID_OFFSET)]
sti
int 25h
mov byte [es:(si + _STATE_OFFSET)], 0
dec word [ds:RunNum]
pop ax
pop bx
pop cx
mov byte[cs:CLOCKON],1
%endmacro
KillCommonProg:
ReleaseProg
;杀死线程
mov bx, ax
push ax
mov ax, MaxRunNum - 1
KillThread:
push ax
mul cx
mov si, ax
pop ax
cmp byte [es:(si + _STATE_OFFSET)], 0 ; 空进程
je NOTTHREAD
cmp byte [es:(si + _KIND_OFFSET)], 2; 等于则线程
jne NOTTHREAD
cmp byte [es:(si + _PARENT_ID_OFFSET)], bl
jne NOTTHREAD
ReleaseProg
NOTTHREAD:
dec ax
jg KillThread
pop ax
jmp FindUserProg
GoodUserProg:
mov word[ds:RunID], ax
LOAD_PCB:
;Parameter: ax = RunID
;Stack: *
;Restart RunID(ax)
;Must have a progress, it is Shell :-)
;ES,DS,DI,SI,BP,SP,BX,DX,CX,AX,SS,IP,CS,FLAGS
mov bx,PCBSize
mul bx
;add ax, Processes; current process PCB
mov bx, ax
;Now DS is kernel DS
LoadReg SP
mov ax, word[es:(bx + _SS_OFFSET)]
mov ss, ax
mov ax, word[es:(bx + _FLAGS_OFFSET)]
push ax
mov ax, word[es:(bx + _CS_OFFSET)]
push ax
mov ax, word[es:(bx + _IP_OFFSET)]
push ax
LoadReg DI
LoadReg SI
LoadReg BP
;LoadReg ES
mov ax, es
mov ds, ax
mov ax, [es:(bx + _ES_OFFSET)]
mov es, ax
mov cx, [bx + _CX_OFFSET]
mov dx, [bx + _DX_OFFSET]
mov ax, [bx + _DS_OFFSET]
push ax
mov ax, [bx + _BX_OFFSET]
push ax
;*/flags/cs/ip/ds/bx
mov ax, [bx + _AX_OFFSET]
pop bx
pop ds
push ax
mov al,20h
out 20h,al
out 0A0h,al
pop ax
;sti
iret
%macro SetOffset 1
%1_OFFSET equ (%1 - Processes)
%endmacro
DATA:
AX_SAVE dw 0
BX_SAVE dw 0
CX_SAVE dw 0
DX_SAVE dw 0
IVT:
INT09HORG dd 0
INT09H_FLAG db 0
PCBCONST:
PCBSize equ FirstProcessEnd - Processes
SetOffset _ID
SetOffset _UID
SetOffset _STATE
SetOffset _NAME
SetOffset _SIZE
SetOffset _SSIZE
SetOffset _SEG
SetOffset _KIND
SetOffset _PARENT_ID
SetOffset _PRIORITY
SetOffset _ES
SetOffset _DS
SetOffset _DI
SetOffset _SI
SetOffset _BP
SetOffset _SP
SetOffset _BX
SetOffset _DX
SetOffset _CX
SetOffset _AX
SetOffset _SS
SetOffset _IP
SetOffset _CS
SetOffset _FLAGS
ProcessesTable:
RunID dw 0 ; default to open shell
UserID db 0
RunNum dw 1
PRIORITY_COUNT db 0
ProcessIDAssigner dw 1; 进程 ID 分配
CLOCKON db 1
Processes:
_ID db 0
_UID db 0
_STATE db 0 ; 结束态0, 运行态1
_NAME db "0123456789ABCDEF" ; 16 bytes
_KIND db 0
_PARENT_ID db 0
_BLOCK_NEXT db 0
_PRIORITY db 0
_SEG dw 0
_SSIZE dw 0
_SIZE dw 0
_ES dw 0
_DS dw 0
_DI dw 0
_SI dw 0
_BP dw 0
_SP dw 0
_BX dw 0
_DX dw 0
_CX dw 0
_AX dw 0
_SS dw 0
_IP dw 0
_CS dw 0
_FLAGS dw 512
FirstProcessEnd: