-
Notifications
You must be signed in to change notification settings - Fork 7
/
monitor.asm
executable file
·385 lines (360 loc) · 10.2 KB
/
monitor.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
;GWMON-80 v0.1.4 for 8080/8085/Z80 and Compatibles
;Copyright (c) 2019 The Glitch Works
;http://www.glitchwrks.com
;
;See LICENSE included in the project root for licensing
;information.
;
;*** STOP! THIS CODE WILL NOT RUN BY ITSELF! ***
;
;This is the base monitor. Consult README for information
;on including the I/O module specific to your system.
ORG XXXXH ;See README for more info
;Initialization and sign-on message
LOG: JMP SETUP ;See README for more info
SE1: LXI H, LOGMSG$
CALL STROUT
LXI H, MSG$
CALL STROUT
;Main command loop
CMDLP: LXI H, PROMPT$
CALL STROUT
LXI H, CMDLP ; Get CMDLP address in HL
PUSH H ; Push HL, prime stack for RET to CMDLP
CALL CIN
ANI 5Fh
CPI 'D'
JZ MEMDMP
CPI 'E'
JZ EDMEM
CPI 'G'
JZ GO
CPI 'O'
JZ OUTPUT
CPI 'I'
JZ INPUT
CPI 'L'
JZ LOAD
LXI H, ERR$
JMP ERROUT
;Get a port address, write byte out
OUTPUT: CALL SPCOUT
CALL GETHEX
MOV B, A
CALL SPCOUT
CALL GETHEX
CALL JMPOUT
RET
;Input from port, print contents
INPUT: CALL SPCOUT
CALL GETHEX
MOV B, A
CALL SPCOUT
MOV A, B
CALL JMPIN
CALL HEXOUT
RET
;Edit memory from a starting address until X is
;pressed. Display mem loc, contents, and results
;of write.
EDMEM: CALL SPCOUT
CALL ADRIN
MOV H, D
MOV L, E
ED1: CALL CRLF
CALL ADROUT
CALL SPCOUT
MVI A, ':'
CALL COUT
CALL SPCOUT
CALL DMPLOC
CALL SPCOUT
CALL GETHEX
RC
MOV M, A
CALL SPCOUT
CALL DMPLOC
INX H
JMP ED1
;Get an address and jump to it
GO: CALL SPCOUT
CALL ADRIN
MOV H, D
MOV L, E
PCHL
;Dump memory between two address locations
MEMDMP: CALL SPCOUT
CALL ADRIN
MOV H, D ; Start in HL
MOV L, E
MVI C, 10h
CALL SPCOUT
CALL ADRIN ; End in DE
MD1: CALL CRLF
CALL DMP16
MOV A, D ; High byte of end address
CMP H ; Compare current high address
RM ; Done if current high > end high
MOV A, E ; Low byte of end address
CMP L ; Compare current low address
JC MD2 ; Current low > end low, check for rollover
JMP MD1 ; Continue dumping memory
MD2: MOV A, D ; High byte of end address
CMP H ; Are high bytes the same?
JNZ MD1 ; Keep going if upper bytes aren't the same
RET ; Done if they are
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;DMP16 -- Dump 16 consecutive memory locations
;
;pre: HL pair contains starting memory address
;post: memory from HL to HL + 16 printed
;post: HL incremented to HL + 16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DMP16: CALL ADROUT
CALL SPCOUT
MVI A, ':'
CALL COUT
MVI C, 10h
DM1: CALL SPCOUT
CALL DMPLOC
INX H
DCR C
RZ
JMP DM1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;DMPLOC -- Print a byte at HL to console
;
;pre: HL pair contains address of byte
;post: byte at HL printed to console
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DMPLOC: MOV A, M
CALL HEXOUT
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;HEXOUT -- Output byte to console as hex
;
;pre: A register contains byte to be output
;post: byte is output to console as hex
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
HEXOUT: PUSH B
MOV B, A
RRC
RRC
RRC
RRC
ANI 0Fh
CALL HEXASC
CALL COUT
MOV A, B
ANI 0Fh
CALL HEXASC
CALL COUT
POP B
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;HEXASC -- Convert nybble to ASCII char
;
;pre: A register contains nybble
;post: A register contains ASCII char
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
HEXASC: ADI 90h
DAA
ACI 40h
DAA
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;ADROUT -- Print an address to the console
;
;pre: HL pair contains address to print
;post: HL printed to console as hex
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADROUT: MOV A, H
CALL HEXOUT
MOV A, L
CALL HEXOUT
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;ADRIN -- Get an address word from console
;
;pre: none
;post: DE contains address from console
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ADRIN: CALL GETHEX
MOV D, A
CALL GETHEX
MOV E, A
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;GETHEX -- Get byte from console as hex
;
;pre: none
;post: A register contains byte from hex input
;post: Carry flag set if X was received
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GETHEX: PUSH D
CALL CIN
CPI 'X'
JZ GE2
CALL ASCHEX
RLC
RLC
RLC
RLC
MOV D, A
CALL CIN
CALL ASCHEX
ORA D
GE1: POP D
RET
GE2: STC
JMP GE1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;ASCHEX -- Convert ASCII coded hex to nybble
;
;pre: A register contains ASCII coded nybble
;post: A register contains nybble
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ASCHEX: SUI 30h
CPI 0Ah
RM
ANI 5Fh
SUI 07h
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;JMPOUT -- Output to a dynamic port
;
;pre: B register contains the port to output to
;pre: A register contains the byte to output
;post: byte is output
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
JMPOUT: MVI C, 0D3h
CALL GOBYT
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;JMPIN -- Input from a dynamic port
;
;pre: A register contains the port to input from
;post: A register contains port value
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
JMPIN: MVI C, 0DBh
MOV B, A
CALL GOBYT
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;GOBYT -- Push a two-byte instruction and RET
; and jump to it
;
;pre: B register contains operand
;pre: C register contains opcode
;post: code executed, returns to caller
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GOBYT: LXI H, 0000
DAD SP
DCX H
MVI M, 0C9h
DCX H
MOV M, B
DCX H
MOV M, C
PCHL
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;SPCOUT -- Print a space to the console
;
;pre: none
;post: 0x20 printed to console
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SPCOUT: MVI A, ' '
CALL COUT
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;STROUT -- Print a null-terminated string
;
;pre: HL contains pointer to start of a null-
; terminated string
;post: string at HL printed to console
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
STROUT: MOV A, M
CPI 00
RZ
CALL COUT
INX H
JMP STROUT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;ERROUT -- Print a null-terminated error string
;
;pre: HL contains pointer to start of a null-
; terminated string
;post: string at HL printed to console
;post: program execution returned to command loop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ERROUT: CALL CRLF
CALL STROUT
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;CRLF -- Print a CR, LF
;
;Preserves HL
;
;pre: none
;post: CR, LF printed to console
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CRLF: PUSH H
LXI H, CRLF$
CALL STROUT
POP H
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;LOAD -- Load an Intel HEX file from console
;
;post: Intel HEX file loaded, or error printed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LOAD: CALL CRLF ; Newline
LOAD1: CALL CINNE
CPI ':'
JNZ LOAD1 ; Wait for start colon
CALL COUT
CALL GETHEX ; Get record length
MOV B, A ; Record length in B
MOV C, A ; Start checksumming in C
CALL GETHEX ; Start address high byte
MOV H, A ; Store in H
ADD C
MOV C, A ; Checksum
CALL GETHEX ; Start address low byte
MOV L, A ; Store in L
ADD C
MOV C, A ; Checksum
CALL GETHEX ; Get record type
MOV D, A ; Store record type in D
ADD C
MOV C, A ; Checksum record type
MOV A, B ; Check record length
ANA A
JZ LOAD4 ; Length == 0, done getting data
LOAD2: CALL GETHEX ; This is the main record processing loop
MOV M, A ; Store char at HL
ADD C
MOV C, A ; Checksum
INX H ; Move memory pointer up
DCR B
JNZ LOAD2 ; Not done with the line
LOAD3: CALL GETHEX ; Get checksum byte
ADD C
JNZ CSUMER ; Checksum bad, print error
ORA D
JZ LOAD ; Record Type 00, keep going
LOAD4: CALL CINNE ; Done getting data, silently eat chars
CPI 10 ; Check for LF
JNZ LOAD4
RET ; Got LF, return to command loop
CSUMER: LXI H, CSERR$ ; Print checksum error to console
JMP ERROUT ; RET from ERROUT will return to command loop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Monitor Strings
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LOGMSG$: db 13, 10, 10, 'GWMON-80 0.1.4 for 8080/8085/Z80 and Compatible', 13, 10
db 'Copyright (c) 2019 The Glitch Works', 0
PROMPT$: db 13, 10, 10, '>', 0
CSERR$: db 'CHECKSUM '
ERR$: db 'ERROR', 0
CRLF$: db 13, 10, 0