-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path42.asm
243 lines (196 loc) · 5.96 KB
/
42.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
; multitasking and dynamic thread registration
[org 0x0100]
jmp start
; PCB layout:
; ax,bx,cx,dx,si,di,bp,sp,ip,cs,ds,ss,es,flags,next, time , dummy
; 0, 2, 4, 6, 8,10,12,14,16,18,20,22,24, 26 , 28 , 30 , 32
pcb: times 32*17 dw 0 ; space for 32 PCBs
stack: times 32*256 dw 0 ; space for 32, 512 byte stacks
nextpcb: dw 1 ; index of next free pcb
current: dw 0 ; index of current pcb
lineno: dw 0 ; line number for next thread
; subroutine to print a number on screen
; takes the row no, column no, and number to be printed as parameters
printnum:
push bp
mov bp, sp
push es
push ax
push bx
push cx
push dx
push di
mov di, 80 ; load di with columns per row
mov ax, [bp+8] ; load ax with row number
mul di ; multiply with columns per row
mov di, ax ; save result in di
add di, [bp+6] ; add column number
shl di, 1 ; turn into byte count
add di, 8 ; to end of number location
mov ax, 0xb800
mov es, ax ; point es to video base
mov ax, [bp+4] ; load number in ax
mov bx, 16 ; use base 16 for division
mov cx, 4 ; initialize count of digits
nextdigit:
mov dx, 0 ; zero upper half of dividend
div bx ; divide by 10
add dl, 0x30 ; convert digit into ascii value
cmp dl, 0x39 ; is the digit an alphabet
jbe skipalpha ; no, skip addition
add dl, 7 ; yes, make in alphabet code
skipalpha:
mov dh, 0x07 ; attach normal attribute
mov [es:di], dx ; print char on screen
sub di, 2 ; to previous screen location
loop nextdigit ; if no divide it again
pop di
pop dx
pop cx
pop bx
pop ax
pop es
pop bp
ret 6
; mytask subroutine to be run as a thread
; takes line number as parameter
mytask:
push bp
mov bp, sp
sub sp, 2 ; thread local variable
push ax
push bx
mov ax, [bp+4] ; load line number parameter
mov bx, 70 ; use column number 70
mov word [bp-2], 0 ; initialize local variable
printagain:
push ax ; line number
push bx ; column number
push word [bp-2] ; number to be printed
call printnum ; print the number
inc word [bp-2] ; increment the local variable
jmp printagain ; infinitely print
pop bx
pop ax
mov sp, bp
pop bp
ret
; subroutine to register a new thread
; takes the segment, offset, of the thread routine and a parameter
; for the target thread subroutine
initpcb:
push bp
mov bp, sp
push ax
push bx
push cx
push si
mov bx, [nextpcb] ; read next available pcb index
cmp bx, 32 ; are all PCBs used
je exit ; yes, exit
mov cl, 5
shl bx, cl ; multiply by 32 for pcb start
mov ax, [bp+8] ; read segment parameter
mov [pcb+bx+18], ax ; save in pcb space for cs
mov ax, [bp+6] ; read offset parameter
mov [pcb+bx+16], ax ; save in pcb space for ip
mov [pcb+bx+22], ds ; set stack to our segment
mov si, [nextpcb] ; read this pcb index
mov cl, 9
shl si, cl ; multiply by 512
add si, 256*2+stack ; end of stack for this thread
mov ax, [bp+4] ; read parameter for subroutine
sub si, 2 ; decrement thread stack pointer
mov [si], ax ; pushing param on thread stack
sub si, 2 ; space for return address
mov [pcb+bx+14], si ; save si in pcb space for sp
mov word [pcb+bx+26], 0x0200 ; initialize thread flags
mov word[pcb+bx+30],10 ; initialize the timer
mov ax, [pcb+28] ; read next of 0th thread in ax
mov [pcb+bx+28], ax ; set as next of new thread
mov ax, [nextpcb] ; read new thread index
mov [pcb+28], ax ; set as next of 0th thread
inc word [nextpcb] ; this pcb is now used
exit:
pop si
pop cx
pop bx
pop ax
pop bp
ret 6
; timer interrupt service routine
timer:
push ds
push bx
push cs
pop ds ; initialize ds to data segment
mov bx, [current] ; read index of current in bx
shl bx, 1
shl bx, 1
shl bx, 1
shl bx, 1
shl bx, 1 ; multiply by 32 for pcb start
mov [pcb+bx+0], ax ; save ax in current pcb
mov [pcb+bx+4], cx ; save cx in current pcb
mov [pcb+bx+6], dx ; save dx in current pcb
mov [pcb+bx+8], si ; save si in current pcb
mov [pcb+bx+10], di ; save di in current pcb
mov [pcb+bx+12], bp ; save bp in current pcb
mov [pcb+bx+24], es ; save es in current pcb
pop ax ; read original bx from stack
mov [pcb+bx+2], ax ; save bx in current pcb
pop ax ; read original ds from stack
mov [pcb+bx+20], ax ; save ds in current pcb
pop ax ; read original ip from stack
mov [pcb+bx+16], ax ; save ip in current pcb
pop ax ; read original cs from stack
mov [pcb+bx+18], ax ; save cs in current pcb
pop ax ; read original flags from stack
mov [pcb+bx+26], ax ; save cs in current pcb
mov [pcb+bx+22], ss ; save ss in current pcb
mov [pcb+bx+14], sp ; save sp in current pcb
dec word[pcb+bx+30] ; decrement in timer
timeEnd:
mov bx, [pcb+bx+28] ; read next pcb of this pcb
mov [current], bx ; update current to new pcb
mov cl, 5
shl bx, cl ; multiply by 32 for pcb start
cmp word[pcb+bx+30],0
je timeEnd
;deleteIt
;deleteIt:
mov cx, [pcb+bx+4] ; read cx of new process
mov dx, [pcb+bx+6] ; read dx of new process
mov si, [pcb+bx+8] ; read si of new process
mov di, [pcb+bx+10] ; read diof new process
mov bp, [pcb+bx+12] ; read bp of new process
mov es, [pcb+bx+24] ; read es of new process
mov ss, [pcb+bx+22] ; read ss of new process
mov sp, [pcb+bx+14] ; read sp of new process
push word [pcb+bx+26] ; push flags of new process
push word [pcb+bx+18] ; push cs of new process
push word [pcb+bx+16] ; push ip of new process
push word [pcb+bx+20] ; push ds of new process
mov al, 0x20
out 0x20, al ; send EOI to PIC
mov ax, [pcb+bx+0] ; read ax of new process
mov bx, [pcb+bx+2] ; read bx of new process
pop ds ; read ds of new process
iret ; return to new process
start:
xor ax, ax
mov es, ax ; point es to IVT base
cli
mov word [es:8*4], timer
mov [es:8*4+2], cs ; hook timer interrupt
sti
nextkey:
xor ah, ah ; service 0 – get keystroke
int 0x16 ; bios keyboard services
push cs ; use current code segment
mov ax, mytask
push ax ; use mytask as offset
push word [lineno] ; thread parameter
call initpcb ; register the thread
inc word [lineno] ; update line number
jmp nextkey ; wait for next keypress