-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprocs.asm
483 lines (370 loc) · 8.03 KB
/
procs.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
TITLE Procedure library
INCLUDE Irvine32.inc
INCLUDE defs.inc
EXTERN curTok:BYTE, vStack:SDWORD, vHeap:SDWORD, insBuf:BYTE, argBuf:SDWORD
EXTERN lblBuf:SDWORD, sPtr:PTR SDWORD, iCount:DWORD, aCount:DWORD, lblPtr:DWORD
.code
GetNextChar PROC USES eax edx ecx,
fileHandle:DWORD
; Reads the next char into the buffer
; Receives: EBP + 8 = fileHandle
; Returns: Sets ZF if reach eof
mov eax, fileHandle
mov edx, OFFSET curTok
mov ecx, 1
call ReadFromFile
test eax, eax
ret
GetNextChar ENDP
GetArg PROC USES ebx,
fileHandle:DWORD
; Gets a number/label argument
; Labels all treated as unsigned
; Does not produce Tmin properly
; Receives: EBP + 8 = fileHandle
; Returns: EAX = Signed int
; ZF is set if reached EOF
; Note: To indicate zero, use [LF] (pref), [SP/TB][LF], or [SP/TB][SP][LF]
mov eax, 0
mov bl, 0 ; Sign
Start:
M_GetChar
jz Done ; Invalid input
ifTb curTok
jne NotNeg
mov bl, 1 ; Negative number
jmp Next
NotNeg:
ifLf curTok
je DoNeg ; Single LF, arg is 0
ifSp curTok
je Next ; Num is positive
jmp Start ; Not a token
Next:
shl eax, 1 ; prepare next bit
NotToken:
M_GetChar
jz Done ; Invalid input
ifTb curTok
jne NotTab
or eax, 1 ; Set bit if tab
jmp Next
NotTab:
ifLf curTok
je DoNeg ; Lf signifies the end
ifSp curTok
jne NotToken ; Not a token, cannot shl
jmp Next ; Space, don't need to set bit but must shl
DoNeg:
shr eax, 1 ; shifted once too many (before LF was read)
cmp bl, 0
je ClrError ; Num is pos, no need to do anyth
neg eax ; Num is negative, negate
ClrError:
or bl, 1 ; clear ZF on a successful return from the function
Done:
ret
GetArg ENDP
GetLabelDest PROC USES edi ebx
; Gets the line pointed to by label in eax.
; Receives: EAX = label
; Returns: EAX = destination
mov ebx, 0
mov edi, lblPtr
Top:
cmp eax, lblBuf[ebx]
je Found
add ebx, 2 * TYPE SDWORD
cmp ebx, edi
jl Top
mov eax, -2 ; Not found, will be -1 after esi inc
ret
Found:
mov eax, lblBuf[ebx + TYPE SDWORD]
ret
GetLabelDest ENDP
vPush PROC USES eax ebx
; PUSH function
; Receives: ESI = offset from argBuf
; Returns: NA
mov eax, sPtr
FetchArg ebx
mov [eax], ebx
add sPtr, TYPE SDWORD
ret
vPush ENDP
vCopy PROC USES eax ebx
; Copy nth element from stack ptr (0 indexed) to top of stack
; Receives: ESI = offset from argBuf
; Returns: NA
FetchArg eax
mov ebx, sPtr
shl eax, 2 ; Mul by TYPE SDWORD
sub ebx, eax
sub ebx, TYPE SDWORD ; Zero indexed
mov eax, vStack[eax]
mov ebx, sPtr
mov [ebx], eax
add sPtr, TYPE SDWORD
ret
vCopy ENDP
vSlide PROC USES eax ebx ecx
; Slides n items off top of stack, excluding top item
; Receives: ESI = offset from argBuf
; Returns: NA
FetchArg eax
shl eax, 2
mov ebx, sPtr
sub sPtr, eax ; Adjust stack ptr
sub ebx, TYPE SDWORD ; Location of top elem
mov ecx, ebx
sub ecx, eax ; Move top elem here
mov eax, [ebx]
mov [ecx], eax ; Moved
ret
vSlide ENDP
vDup PROC USES eax ebx
; Duplicates the top element of the stack
; Receives: NA
; Returns: NA
mov eax, sPtr
mov ebx, [eax - TYPE SDWORD]
mov [eax], ebx
add sPtr, TYPE SDWORD
ret
vDup ENDP
vSwap PROC USES eax ebx
; Swaps top two elements of stack
; Receives: NA
; Returns: NA
mov eax, sPtr
mov ebx, [eax - TYPE SDWORD]
xchg ebx, [eax - 2 * TYPE SDWORD]
mov [eax - TYPE SDWORD], ebx
ret
vSwap ENDP
vDiscard PROC
; Discards top element of stack
; Receives: NA
; Returns: NA
sub sPtr, TYPE SDWORD
ret
vDiscard ENDP
vAdd PROC USES eax ebx
; Adds top two elements of stack, replaces them with the sum
; Receives: NA
; Returns: NA
sub sPtr, TYPE SDWORD
mov eax, sPtr
mov ebx, [eax]
add [eax - TYPE SDWORD], ebx
ret
vAdd ENDP
vSub PROC USES eax ebx
; Subs the top element from the one preceding it, replaces them
; Receives: NA
; Returns: NA
sub sPtr, TYPE SDWORD
mov eax, sPtr
mov ebx, [eax]
sub [eax - TYPE SDWORD], ebx
ret
vSub ENDP
vMul PROC USES eax ebx
; Multiplies the top two elements, replaces them
; Receives: NA
; Returns: NA
sub sPtr, TYPE SDWORD
mov ebx, sPtr
mov eax, [ebx - TYPE SDWORD]
imul eax, [ebx]
mov [ebx - TYPE SDWORD], eax
ret
vMul ENDP
vDiv PROC USES eax ebx ecx edx
; Integer division
; Receives: NA
; Returns: NA
sub sPtr, TYPE SDWORD
mov ecx, sPtr
mov ebx, [ecx]
mov eax, [ecx - TYPE SDWORD]
cdq
idiv ebx
mov [ecx - TYPE SDWORD], eax
ret
vDiv ENDP
vMod PROC USES eax ebx ecx edx
; Modulus
; Receives: NA
; Returns: NA
sub sPtr, TYPE SDWORD
mov ecx, sPtr
mov ebx, [ecx]
mov eax, [ecx - TYPE SDWORD]
cdq
idiv ebx
mov [ecx - TYPE SDWORD], edx
ret
vMod ENDP
vStore PROC USES eax ebx
; Stores a value into memory.
; Push the offset (zero-indexed) then the value, then call this command
; Arguments are cleaned up
; Receives: NA
; Returns: NA
mov eax, sPtr
mov ebx, [eax - 2 * TYPE SDWORD]
mov eax, [eax - TYPE SDWORD]
mov vHeap[ebx * TYPE SDWORD], eax
sub sPtr, 2 * TYPE SDWORD
ret
vStore ENDP
vLoad PROC USES eax ebx
; Loads a value from memory into top position on stack
; Push the offset (zero-indexed) and then call this command
; Args are removed before putting onto stack
; Receives: NA
; Returns: NA
mov eax, sPtr
mov eax, [eax - TYPE SDWORD]
mov eax, vHeap[eax * TYPE SDWORD]
mov ebx, sPtr
mov [ebx - TYPE SDWORD], eax
ret
vLoad ENDP
vLabel PROC
; Doesn't do anything. Labels are processed in the first pass.
ret
vLabel ENDP
vCall PROC USES eax
; Calls a subroutine by a 32-bit label.
; Sets up the requisite stack frame (well, just the eip).
; No error checking yet
; Receives: ESI = instruction pointer
; Returns: NA
mov eax, sPtr
mov [eax], esi ; esi not decrem., so when incremented, points to next ins.
add sPtr, TYPE SDWORD
FetchArg eax
call GetLabelDest
mov esi, eax
ret
vCall ENDP
vJmp PROC USES eax
; Jumps to a specified label (i.e. currently instruction number)
; Receives: ESI = instruction pointer
; Returns: NA
FetchArg eax
call GetLabelDest
mov esi, eax
ret
vJmp ENDP
vJz PROC USES eax ebx
; Jumps to a specified label if top of stack is 0
; Receives: ESI = instruction pointer
; Returns: NA
mov eax, sPtr
mov ebx, 0
cmp [eax - TYPE SDWORD], ebx
jne NoJump
FetchArg eax
call GetLabelDest
mov esi, eax
NoJump:
ret
vJz ENDP
vJs PROC USES eax ebx
; Jumps to a specified label if top of stack is neg
; Receives: ESI = instruction pointer
; Returns: NA
mov eax, sPtr
mov ebx, 0
cmp [eax - TYPE SDWORD], ebx
jnl NoJump
FetchArg eax
call GetLabelDest
mov esi, eax
NoJump:
ret
vJs ENDP
vRet PROC
; Returns from a function call. Make sure local vars are cleaned first!
; Receives: NA
; Returns: NA
sub sPtr, TYPE SDWORD
mov esi, sPtr
mov esi, [esi]
ret
vRet ENDP
vEnd PROC
; Ends the program
; Receives: NA
; Returns: NA
mov iCount, 0
ret
vEnd ENDP
vOChar PROC USES eax
; Outputs an ASCII formatted char from the top of the stack
; Removes the char at the top of the stack
; Auto-compensates for windows CRLF
; Receives: NA
; Returns: NA
sub sPtr, TYPE SDWORD
mov eax, sPtr
mov eax, [eax]
cmp eax, 0Ah ; Handle CRLF
jne Write
call Crlf
jmp After
Write:
call WriteChar
After:
ret
vOChar ENDP
vONum PROC USES eax
; Outputs a 32-bit signed decimal num from the top of the stack
; Removes the number from top of stack
; Receives: NA
; Returns: NA
sub sPtr, TYPE SDWORD
mov eax, sPtr
mov eax, [eax]
call WriteInt
ret
vONum ENDP
vIChar PROC USES eax ebx ecx
; Reads in a single ASCII character onto the top of the stack
; Char is echoed onto screen
; If a control key is pressed, result is 0
; Receives: NA
; Returns: NA
mov ebx, sPtr
call ReadChar
cmp al, 0dh ; Handle CRLF echoing; 0dh is read when enter pressed
jne NotCR
call Crlf
mov eax, 0ah
jmp Put
NotCR:
call WriteChar
Put:
movzx ecx, al
mov [ebx], ecx
add sPtr, TYPE SDWORD
ret
vIChar ENDP
vINum PROC USES eax ebx
; Reads in a signed 32-bit decimal int from the screen onto the stack
; 0 if integer overflows
; Currently puts an ugly + for positive nos.
; Will eventually write a subroutine for this
; Receives: NA
; Returns: NA
mov ebx, sPtr
call ReadInt
mov [ebx], eax
add sPtr, TYPE SDWORD
ret
vINum ENDP
END