diff options
Diffstat (limited to 'v2.0/source/DEBCOM1.ASM')
| -rw-r--r-- | v2.0/source/DEBCOM1.ASM | 694 |
1 files changed, 694 insertions, 0 deletions
diff --git a/v2.0/source/DEBCOM1.ASM b/v2.0/source/DEBCOM1.ASM new file mode 100644 index 0000000..8e992d9 --- /dev/null +++ b/v2.0/source/DEBCOM1.ASM | |||
| @@ -0,0 +1,694 @@ | |||
| 1 | TITLE PART1 DEBUGGER COMMANDS | ||
| 2 | |||
| 3 | ; Routines to perform debugger commands except ASSEMble and UASSEMble | ||
| 4 | |||
| 5 | .xlist | ||
| 6 | .xcref | ||
| 7 | INCLUDE DEBEQU.ASM | ||
| 8 | INCLUDE DOSSYM.ASM | ||
| 9 | .cref | ||
| 10 | .list | ||
| 11 | |||
| 12 | CODE SEGMENT PUBLIC BYTE 'CODE' | ||
| 13 | CODE ENDS | ||
| 14 | |||
| 15 | CONST SEGMENT PUBLIC BYTE | ||
| 16 | |||
| 17 | EXTRN SYNERR:BYTE | ||
| 18 | |||
| 19 | EXTRN DISPB:WORD,DSIZ:BYTE,DSSAVE:WORD | ||
| 20 | if sysver | ||
| 21 | EXTRN CIN:DWORD,PFLAG:BYTE | ||
| 22 | endif | ||
| 23 | |||
| 24 | CONST ENDS | ||
| 25 | |||
| 26 | DATA SEGMENT PUBLIC BYTE | ||
| 27 | |||
| 28 | EXTRN DEFLEN:WORD,BYTEBUF:BYTE,DEFDUMP:BYTE | ||
| 29 | |||
| 30 | DATA ENDS | ||
| 31 | |||
| 32 | DG GROUP CODE,CONST,DATA | ||
| 33 | |||
| 34 | |||
| 35 | CODE SEGMENT PUBLIC BYTE 'CODE' | ||
| 36 | ASSUME CS:DG,DS:DG,ES:DG,SS:DG | ||
| 37 | |||
| 38 | |||
| 39 | PUBLIC HEXCHK,GETHEX1,PRINT,DSRANGE,ADDRESS,HEXIN,PERROR | ||
| 40 | PUBLIC GETHEX,GET_ADDRESS,GETEOL,GETHX,PERR | ||
| 41 | PUBLIC PERR,MOVE,DUMP,ENTER,FILL,SEARCH,DEFAULT | ||
| 42 | if sysver | ||
| 43 | PUBLIC IN | ||
| 44 | EXTRN DISPREG:NEAR,DEVIOCALL:NEAR | ||
| 45 | endif | ||
| 46 | |||
| 47 | EXTRN OUT:NEAR,CRLF:NEAR,OUTDI:NEAR,OUTSI:NEAR,SCANP:NEAR | ||
| 48 | EXTRN SCANB:NEAR,BLANK:NEAR,TAB:NEAR,PRINTMES:NEAR,COMMAND:NEAR | ||
| 49 | EXTRN HEX:NEAR,BACKUP:NEAR | ||
| 50 | |||
| 51 | |||
| 52 | DEBCOM1: | ||
| 53 | |||
| 54 | ; RANGE - Looks for parameters defining an address range. | ||
| 55 | ; The first parameter is the starting address. The second parameter | ||
| 56 | ; may specify the ending address, or it may be preceded by | ||
| 57 | ; "L" and specify a length (4 digits max), or it may be | ||
| 58 | ; omitted and a length of 128 bytes is assumed. Returns with | ||
| 59 | ; segment in AX, displacement in DX, and length in CX. | ||
| 60 | |||
| 61 | DSRANGE: | ||
| 62 | MOV BP,[DSSAVE] ; Set default segment to DS | ||
| 63 | MOV [DEFLEN],128 ; And default length to 128 bytes | ||
| 64 | RANGE: | ||
| 65 | CALL ADDRESS | ||
| 66 | PUSH AX ; Save segment | ||
| 67 | PUSH DX ; Save offset | ||
| 68 | CALL SCANP ; Get to next parameter | ||
| 69 | MOV AL,[SI] | ||
| 70 | CMP AL,"L" ; Length indicator? | ||
| 71 | JE GETLEN | ||
| 72 | MOV DX,[DEFLEN] ; Default length | ||
| 73 | CALL HEXIN ; Second parameter present? | ||
| 74 | JC GetDef ; If not, use default | ||
| 75 | MOV CX,4 | ||
| 76 | CALL GETHEX ; Get ending address (same segment) | ||
| 77 | MOV CX,DX ; Low 16 bits of ending addr. | ||
| 78 | POP DX ; Low 16 bits of starting addr. | ||
| 79 | SUB CX,DX ; Compute range | ||
| 80 | JAE DSRNG2 | ||
| 81 | DSRNG1: JMP PERROR ; Negative range | ||
| 82 | DSRNG2: INC CX ; Include last location | ||
| 83 | JCXZ DSRNG1 ; Wrap around error | ||
| 84 | POP AX ; Restore segment | ||
| 85 | RET | ||
| 86 | GetDef: | ||
| 87 | POP CX ; get original offset | ||
| 88 | PUSH CX ; save it | ||
| 89 | NEG CX ; rest of segment | ||
| 90 | JZ RngRet ; use default | ||
| 91 | CMP CX,DX ; more room in segment? | ||
| 92 | JAE RngRet ; yes, use default | ||
| 93 | JMP RngRet1 ; no, length is in CX | ||
| 94 | |||
| 95 | GETLEN: | ||
| 96 | INC SI ; Skip over "L" to length | ||
| 97 | MOV CX,4 ; Length may have 4 digits | ||
| 98 | CALL GETHEX ; Get the range | ||
| 99 | RNGRET: | ||
| 100 | MOV CX,DX ; Length | ||
| 101 | RngRet1: | ||
| 102 | POP DX ; Offset | ||
| 103 | MOV AX,CX | ||
| 104 | ADD AX,DX | ||
| 105 | JNC OKRET | ||
| 106 | CMP AX,1 | ||
| 107 | JAE DSRNG1 ; Look for wrap error | ||
| 108 | OKRET: | ||
| 109 | POP AX ; Segment | ||
| 110 | RET | ||
| 111 | |||
| 112 | DEFAULT: | ||
| 113 | ; DI points to default address and CX has default length | ||
| 114 | CALL SCANP | ||
| 115 | JZ USEDEF ; Use default if no parameters | ||
| 116 | MOV [DEFLEN],CX | ||
| 117 | CALL RANGE | ||
| 118 | JMP GETEOL | ||
| 119 | USEDEF: | ||
| 120 | MOV SI,DI | ||
| 121 | LODSW ; Get default displacement | ||
| 122 | MOV DX,AX | ||
| 123 | LODSW ; Get default segment | ||
| 124 | RET | ||
| 125 | |||
| 126 | ; Dump an area of memory in both hex and ASCII | ||
| 127 | |||
| 128 | DUMP: | ||
| 129 | MOV BP,[DSSAVE] | ||
| 130 | MOV CX,DISPB | ||
| 131 | MOV DI,OFFSET DG:DEFDUMP | ||
| 132 | CALL DEFAULT ; Get range if specified | ||
| 133 | MOV DS,AX ; Set segment | ||
| 134 | MOV SI,DX ; SI has displacement in segment | ||
| 135 | |||
| 136 | IF ZIBO | ||
| 137 | PUSH SI ; save SI away | ||
| 138 | AND SI,0FFF0h ; convert to para number | ||
| 139 | CALL OutSI ; display location | ||
| 140 | POP SI ; get SI back | ||
| 141 | MOV AX,SI ; move offset | ||
| 142 | MOV AH,3 ; spaces per byte | ||
| 143 | AND AL,0Fh ; convert to real offset | ||
| 144 | MUL AH ; compute (AL+1)*3-1 | ||
| 145 | OR AL,AL ; set flag | ||
| 146 | JZ InRow ; if xero go on | ||
| 147 | PUSH CX ; save count | ||
| 148 | MOV CX,AX ; move to convenient spot | ||
| 149 | CALL Tab ; move over | ||
| 150 | POP CX ; get back count | ||
| 151 | JMP InRow ; display line | ||
| 152 | ENDIF | ||
| 153 | |||
| 154 | ROW: | ||
| 155 | CALL OUTSI ; Print address at start of line | ||
| 156 | InRow: | ||
| 157 | PUSH SI ; Save address for ASCII dump | ||
| 158 | CALL BLANK | ||
| 159 | BYTE0: | ||
| 160 | CALL BLANK ; Space between bytes | ||
| 161 | BYTE1: | ||
| 162 | LODSB ; Get byte to dump | ||
| 163 | CALL HEX ; and display it | ||
| 164 | POP DX ; DX has start addr. for ASCII dump | ||
| 165 | DEC CX ; Drop loop count | ||
| 166 | JZ ToAscii ; If through do ASCII dump | ||
| 167 | MOV AX,SI | ||
| 168 | TEST AL,CS:(BYTE PTR DSIZ) ; On 16-byte boundary? | ||
| 169 | JZ ENDROW | ||
| 170 | PUSH DX ; Didn't need ASCII addr. yet | ||
| 171 | TEST AL,7 ; On 8-byte boundary? | ||
| 172 | JNZ BYTE0 | ||
| 173 | MOV AL,"-" ; Mark every 8 bytes | ||
| 174 | CALL OUT | ||
| 175 | JMP SHORT BYTE1 | ||
| 176 | ENDROW: | ||
| 177 | CALL ASCII ; Show it in ASCII | ||
| 178 | JMP SHORT ROW ; Loop until count is zero | ||
| 179 | ToAscii: | ||
| 180 | MOV AX,SI ; get offset | ||
| 181 | AND AL,0Fh ; real offset | ||
| 182 | JZ ASCII ; no loop if already there | ||
| 183 | SUB AL,10h ; remainder | ||
| 184 | NEG AL | ||
| 185 | MOV CL,3 | ||
| 186 | MUL CL | ||
| 187 | MOV CX,AX ; number of chars to move | ||
| 188 | CALL Tab | ||
| 189 | ASCII: | ||
| 190 | PUSH CX ; Save byte count | ||
| 191 | MOV AX,SI ; Current dump address | ||
| 192 | MOV SI,DX ; ASCII dump address | ||
| 193 | SUB AX,DX ; AX=length of ASCII dump | ||
| 194 | IF NOT ZIBO | ||
| 195 | ; Compute tab length. ASCII dump always appears on right side | ||
| 196 | ; screen regardless of how many bytes were dumped. Figure 3 | ||
| 197 | ; characters for each byte dumped and subtract from 51, which | ||
| 198 | ; allows a minimum of 3 blanks after the last byte dumped. | ||
| 199 | MOV BX,AX | ||
| 200 | SHL AX,1 ; Length times 2 | ||
| 201 | ADD AX,BX ; Length times 3 | ||
| 202 | MOV CX,51 | ||
| 203 | SUB CX,AX ; Amount to tab in CX | ||
| 204 | CALL TAB | ||
| 205 | MOV CX,BX ; ASCII dump length back in CX | ||
| 206 | ELSE | ||
| 207 | MOV CX,SI ; get starting point | ||
| 208 | DEC CX | ||
| 209 | AND CX,0Fh | ||
| 210 | INC CX | ||
| 211 | AND CX,0Fh | ||
| 212 | ADD CX,3 ; we have the correct number to tab | ||
| 213 | PUSH AX ; save count | ||
| 214 | CALL TAB | ||
| 215 | POP CX ; get count back | ||
| 216 | ENDIF | ||
| 217 | ASCDMP: | ||
| 218 | LODSB ; Get ASCII byte to dump | ||
| 219 | AND AL,7FH ; ASCII uses 7 bits | ||
| 220 | CMP AL,7FH ; Don't try to print RUBOUT | ||
| 221 | JZ NOPRT | ||
| 222 | CMP AL," " ; Check for control characters | ||
| 223 | JNC PRIN | ||
| 224 | NOPRT: | ||
| 225 | MOV AL,"." ; If unprintable character | ||
| 226 | PRIN: | ||
| 227 | CALL OUT ; Print ASCII character | ||
| 228 | LOOP ASCDMP ; CX times | ||
| 229 | POP CX ; Restore overall dump length | ||
| 230 | MOV ES:WORD PTR [DEFDUMP],SI | ||
| 231 | MOV ES:WORD PTR [DEFDUMP+2],DS ; Save last address as default | ||
| 232 | CALL CRLF ; Print CR/LF and return | ||
| 233 | RET | ||
| 234 | |||
| 235 | |||
| 236 | ; Block move one area of memory to another. Overlapping moves | ||
| 237 | ; are performed correctly, i.e., so that a source byte is not | ||
| 238 | ; overwritten until after it has been moved. | ||
| 239 | |||
| 240 | MOVE: | ||
| 241 | CALL DSRANGE ; Get range of source area | ||
| 242 | PUSH CX ; Save length | ||
| 243 | PUSH AX ; Save segment | ||
| 244 | PUSH DX ; Save source displacement | ||
| 245 | CALL ADDRESS ; Get destination address (same segment) | ||
| 246 | CALL GETEOL ; Check for errors | ||
| 247 | POP SI | ||
| 248 | MOV DI,DX ; Set dest. displacement | ||
| 249 | POP BX ; Source segment | ||
| 250 | MOV DS,BX | ||
| 251 | MOV ES,AX ; Destination segment | ||
| 252 | POP CX ; Length | ||
| 253 | CMP DI,SI ; Check direction of move | ||
| 254 | SBB AX,BX ; Extend the CMP to 32 bits | ||
| 255 | JB COPYLIST ; Move forward into lower mem. | ||
| 256 | ; Otherwise, move backward. Figure end of source and destination | ||
| 257 | ; areas and flip direction flag. | ||
| 258 | DEC CX | ||
| 259 | ADD SI,CX ; End of source area | ||
| 260 | ADD DI,CX ; End of destination area | ||
| 261 | STD ; Reverse direction | ||
| 262 | INC CX | ||
| 263 | COPYLIST: | ||
| 264 | MOVSB ; Do at least 1 - Range is 1-10000H not 0-FFFFH | ||
| 265 | DEC CX | ||
| 266 | REP MOVSB ; Block move | ||
| 267 | RET1: RET | ||
| 268 | |||
| 269 | ; Fill an area of memory with a list values. If the list | ||
| 270 | ; is bigger than the area, don't use the whole list. If the | ||
| 271 | ; list is smaller, repeat it as many times as necessary. | ||
| 272 | |||
| 273 | FILL: | ||
| 274 | CALL DSRANGE ; Get range to fill | ||
| 275 | PUSH CX ; Save length | ||
| 276 | PUSH AX ; Save segment number | ||
| 277 | PUSH DX ; Save displacement | ||
| 278 | CALL LIST ; Get list of values to fill with | ||
| 279 | POP DI ; Displacement in segment | ||
| 280 | POP ES ; Segment | ||
| 281 | POP CX ; Length | ||
| 282 | CMP BX,CX ; BX is length of fill list | ||
| 283 | MOV SI,OFFSET DG:BYTEBUF ; List is in byte buffer | ||
| 284 | JCXZ BIGRNG | ||
| 285 | JAE COPYLIST ; If list is big, copy part of it | ||
| 286 | BIGRNG: | ||
| 287 | SUB CX,BX ; How much bigger is area than list? | ||
| 288 | XCHG CX,BX ; CX=length of list | ||
| 289 | PUSH DI ; Save starting addr. of area | ||
| 290 | REP MOVSB ; Move list into area | ||
| 291 | POP SI | ||
| 292 | ; The list has been copied into the beginning of the | ||
| 293 | ; specified area of memory. SI is the first address | ||
| 294 | ; of that area, DI is the end of the copy of the list | ||
| 295 | ; plus one, which is where the list will begin to repeat. | ||
| 296 | ; All we need to do now is copy [SI] to [DI] until the | ||
| 297 | ; end of the memory area is reached. This will cause the | ||
| 298 | ; list to repeat as many times as necessary. | ||
| 299 | MOV CX,BX ; Length of area minus list | ||
| 300 | PUSH ES ; Different index register | ||
| 301 | POP DS ; requires different segment reg. | ||
| 302 | JMP SHORT COPYLIST ; Do the block move | ||
| 303 | |||
| 304 | ; Search a specified area of memory for given list of bytes. | ||
| 305 | ; Print address of first byte of each match. | ||
| 306 | |||
| 307 | SEARCH: | ||
| 308 | CALL DSRANGE ; Get area to be searched | ||
| 309 | PUSH CX ; Save count | ||
| 310 | PUSH AX ; Save segment number | ||
| 311 | PUSH DX ; Save displacement | ||
| 312 | CALL LIST ; Get search list | ||
| 313 | DEC BX ; No. of bytes in list-1 | ||
| 314 | POP DI ; Displacement within segment | ||
| 315 | POP ES ; Segment | ||
| 316 | POP CX ; Length to be searched | ||
| 317 | SUB CX,BX ; minus length of list | ||
| 318 | SCAN: | ||
| 319 | MOV SI,OFFSET DG:BYTEBUF ; List kept in byte buffer | ||
| 320 | LODSB ; Bring first byte into AL | ||
| 321 | DOSCAN: | ||
| 322 | SCASB ; Search for first byte | ||
| 323 | LOOPNE DOSCAN ; Do at least once by using LOOP | ||
| 324 | JNZ RET1 ; Exit if not found | ||
| 325 | PUSH BX ; Length of list minus 1 | ||
| 326 | XCHG BX,CX | ||
| 327 | PUSH DI ; Will resume search here | ||
| 328 | REPE CMPSB ; Compare rest of string | ||
| 329 | MOV CX,BX ; Area length back in CX | ||
| 330 | POP DI ; Next search location | ||
| 331 | POP BX ; Restore list length | ||
| 332 | JNZ TEST ; Continue search if no match | ||
| 333 | DEC DI ; Match address | ||
| 334 | CALL OUTDI ; Print it | ||
| 335 | INC DI ; Restore search address | ||
| 336 | CALL CRLF | ||
| 337 | TEST: | ||
| 338 | JCXZ RET1 | ||
| 339 | JMP SHORT SCAN ; Look for next occurrence | ||
| 340 | |||
| 341 | ; Get the next parameter, which must be a hex number. | ||
| 342 | ; CX is maximum number of digits the number may have. | ||
| 343 | |||
| 344 | GETHX: | ||
| 345 | CALL SCANP | ||
| 346 | GETHX1: | ||
| 347 | XOR DX,DX ; Initialize the number | ||
| 348 | CALL HEXIN ; Get a hex digit | ||
| 349 | JC HXERR ; Must be one valid digit | ||
| 350 | MOV DL,AL ; First 4 bits in position | ||
| 351 | GETLP: | ||
| 352 | INC SI ; Next char in buffer | ||
| 353 | DEC CX ; Digit count | ||
| 354 | CALL HEXIN ; Get another hex digit? | ||
| 355 | JC RETHX ; All done if no more digits | ||
| 356 | STC | ||
| 357 | JCXZ HXERR ; Too many digits? | ||
| 358 | SHL DX,1 ; Multiply by 16 | ||
| 359 | SHL DX,1 | ||
| 360 | SHL DX,1 | ||
| 361 | SHL DX,1 | ||
| 362 | OR DL,AL ; and combine new digit | ||
| 363 | JMP SHORT GETLP ; Get more digits | ||
| 364 | |||
| 365 | GETHEX: | ||
| 366 | CALL GETHX ; Scan to next parameter | ||
| 367 | JMP SHORT GETHX2 | ||
| 368 | GETHEX1: | ||
| 369 | CALL GETHX1 | ||
| 370 | GETHX2: JC PERROR | ||
| 371 | RETHX: CLC | ||
| 372 | HXERR: RET | ||
| 373 | |||
| 374 | |||
| 375 | ; Check if next character in the input buffer is a hex digit | ||
| 376 | ; and convert it to binary if it is. Carry set if not. | ||
| 377 | |||
| 378 | HEXIN: | ||
| 379 | MOV AL,[SI] | ||
| 380 | |||
| 381 | ; Check if AL has a hex digit and convert it to binary if it | ||
| 382 | ; is. Carry set if not. | ||
| 383 | |||
| 384 | HEXCHK: | ||
| 385 | SUB AL,"0" ; Kill ASCII numeric bias | ||
| 386 | JC RET2 | ||
| 387 | CMP AL,10 | ||
| 388 | CMC | ||
| 389 | JNC RET2 ; OK if 0-9 | ||
| 390 | AND AL,5FH | ||
| 391 | SUB AL,7 ; Kill A-F bias | ||
| 392 | CMP AL,10 | ||
| 393 | JC RET2 | ||
| 394 | CMP AL,16 | ||
| 395 | CMC | ||
| 396 | RET2: RET | ||
| 397 | |||
| 398 | ; Process one parameter when a list of bytes is | ||
| 399 | ; required. Carry set if parameter bad. Called by LIST. | ||
| 400 | |||
| 401 | LISTITEM: | ||
| 402 | CALL SCANP ; Scan to parameter | ||
| 403 | CALL HEXIN ; Is it in hex? | ||
| 404 | JC STRINGCHK ; If not, could be a string | ||
| 405 | MOV CX,2 ; Only 2 hex digits for bytes | ||
| 406 | CALL GETHEX ; Get the byte value | ||
| 407 | MOV [BX],DL ; Add to list | ||
| 408 | INC BX | ||
| 409 | GRET: CLC ; Parameter was OK | ||
| 410 | RET | ||
| 411 | STRINGCHK: | ||
| 412 | MOV AL,[SI] ; Get first character of param | ||
| 413 | CMP AL,"'" ; String? | ||
| 414 | JZ STRING | ||
| 415 | CMP AL,'"' ; Either quote is all right | ||
| 416 | JZ STRING | ||
| 417 | STC ; Not string, not hex - bad | ||
| 418 | RET | ||
| 419 | STRING: | ||
| 420 | MOV AH,AL ; Save for closing quote | ||
| 421 | INC SI | ||
| 422 | STRNGLP: | ||
| 423 | LODSB ; Next char of string | ||
| 424 | CMP AL,13 ; Check for end of line | ||
| 425 | JZ PERR ; Must find a close quote | ||
| 426 | CMP AL,AH ; Check for close quote | ||
| 427 | JNZ STOSTRG ; Add new character to list | ||
| 428 | CMP AH,[SI] ; Two quotes in a row? | ||
| 429 | JNZ GRET ; If not, we're done | ||
| 430 | INC SI ; Yes - skip second one | ||
| 431 | STOSTRG: | ||
| 432 | MOV [BX],AL ; Put new char in list | ||
| 433 | INC BX | ||
| 434 | JMP SHORT STRNGLP ; Get more characters | ||
| 435 | |||
| 436 | ; Get a byte list for ENTER, FILL or SEARCH. Accepts any number | ||
| 437 | ; of 2-digit hex values or character strings in either single | ||
| 438 | ; (') or double (") quotes. | ||
| 439 | |||
| 440 | LIST: | ||
| 441 | MOV BX,OFFSET DG:BYTEBUF ; Put byte list in the byte buffer | ||
| 442 | LISTLP: | ||
| 443 | CALL LISTITEM ; Process a parameter | ||
| 444 | JNC LISTLP ; If OK, try for more | ||
| 445 | SUB BX,OFFSET DG:BYTEBUF ; BX now has no. of bytes in list | ||
| 446 | JZ PERROR ; List must not be empty | ||
| 447 | |||
| 448 | ; Make sure there is nothing more on the line except for | ||
| 449 | ; blanks and carriage return. If there is, it is an | ||
| 450 | ; unrecognized parameter and an error. | ||
| 451 | |||
| 452 | GETEOL: | ||
| 453 | CALL SCANB ; Skip blanks | ||
| 454 | JNZ PERROR ; Better be a RETURN | ||
| 455 | RET3: RET | ||
| 456 | |||
| 457 | ; Command error. SI has been incremented beyond the | ||
| 458 | ; command letter so it must decremented for the | ||
| 459 | ; error pointer to work. | ||
| 460 | |||
| 461 | PERR: | ||
| 462 | DEC SI | ||
| 463 | |||
| 464 | ; Syntax error. SI points to character in the input buffer | ||
| 465 | ; which caused error. By subtracting from start of buffer, | ||
| 466 | ; we will know how far to tab over to appear directly below | ||
| 467 | ; it on the terminal. Then print "^ Error". | ||
| 468 | |||
| 469 | PERROR: | ||
| 470 | SUB SI,OFFSET DG:(BYTEBUF-1); How many char processed so far? | ||
| 471 | MOV CX,SI ; Parameter for TAB in CX | ||
| 472 | CALL TAB ; Directly below bad char | ||
| 473 | MOV SI,OFFSET DG:SYNERR ; Error message | ||
| 474 | |||
| 475 | ; Print error message and abort to command level | ||
| 476 | |||
| 477 | PRINT: | ||
| 478 | CALL PRINTMES | ||
| 479 | JMP COMMAND | ||
| 480 | |||
| 481 | ; Gets an address in Segment:Displacement format. Segment may be omitted | ||
| 482 | ; and a default (kept in BP) will be used, or it may be a segment | ||
| 483 | ; register (DS, ES, SS, CS). Returns with segment in AX, OFFSET in DX. | ||
| 484 | |||
| 485 | ADDRESS: | ||
| 486 | CALL GET_ADDRESS | ||
| 487 | JC PERROR | ||
| 488 | ADRERR: STC | ||
| 489 | RET | ||
| 490 | |||
| 491 | GET_ADDRESS: | ||
| 492 | CALL SCANP | ||
| 493 | MOV AL,[SI+1] | ||
| 494 | CMP AL,"S" | ||
| 495 | JZ SEGREG | ||
| 496 | MOV CX,4 | ||
| 497 | CALL GETHX | ||
| 498 | JC ADRERR | ||
| 499 | MOV AX,BP ; Get default segment | ||
| 500 | CMP BYTE PTR [SI],":" | ||
| 501 | JNZ GETRET | ||
| 502 | PUSH DX | ||
| 503 | GETDISP: | ||
| 504 | INC SI ; Skip over ":" | ||
| 505 | MOV CX,4 | ||
| 506 | CALL GETHX | ||
| 507 | POP AX | ||
| 508 | JC ADRERR | ||
| 509 | GETRET: CLC | ||
| 510 | RET | ||
| 511 | SEGREG: | ||
| 512 | MOV AL,[SI] | ||
| 513 | MOV DI,OFFSET DG:SEGLET | ||
| 514 | MOV CX,4 | ||
| 515 | REPNE SCASB | ||
| 516 | JNZ ADRERR | ||
| 517 | INC SI | ||
| 518 | INC SI | ||
| 519 | SHL CX,1 | ||
| 520 | MOV BX,CX | ||
| 521 | CMP BYTE PTR [SI],":" | ||
| 522 | JNZ ADRERR | ||
| 523 | PUSH [BX+DSSAVE] | ||
| 524 | JMP SHORT GETDISP | ||
| 525 | |||
| 526 | SEGLET DB "CSED" | ||
| 527 | |||
| 528 | ; Short form of ENTER command. A list of values from the | ||
| 529 | ; command line are put into memory without using normal | ||
| 530 | ; ENTER mode. | ||
| 531 | |||
| 532 | GETLIST: | ||
| 533 | CALL LIST ; Get the bytes to enter | ||
| 534 | POP DI ; Displacement within segment | ||
| 535 | POP ES ; Segment to enter into | ||
| 536 | MOV SI,OFFSET DG:BYTEBUF ; List of bytes is in byte 2uffer | ||
| 537 | MOV CX,BX ; Count of bytes | ||
| 538 | REP MOVSB ; Enter that byte list | ||
| 539 | RET | ||
| 540 | |||
| 541 | ; Enter values into memory at a specified address. If the | ||
| 542 | ; line contains nothing but the address we go into "enter | ||
| 543 | ; mode", where the address and its current value are printed | ||
| 544 | ; and the user may change it if desired. To change, type in | ||
| 545 | ; new value in hex. Backspace works to correct errors. If | ||
| 546 | ; an illegal hex digit or too many digits are typed, the | ||
| 547 | ; bell is sounded but it is otherwise ignored. To go to the | ||
| 548 | ; next byte (with or without change), hit space bar. To | ||
| 549 | ; back CLDto a previous address, type "-". On | ||
| 550 | ; every 8-byte boundary a new line is started and the address | ||
| 551 | ; is printed. To terminate command, type carriage return. | ||
| 552 | ; Alternatively, the list of bytes to be entered may be | ||
| 553 | ; included on the original command line immediately following | ||
| 554 | ; the address. This is in regular LIST format so any number | ||
| 555 | ; of hex values or strings in quotes may be entered. | ||
| 556 | |||
| 557 | ENTER: | ||
| 558 | MOV BP,[DSSAVE] ; Set default segment to DS | ||
| 559 | CALL ADDRESS | ||
| 560 | PUSH AX ; Save for later | ||
| 561 | PUSH DX | ||
| 562 | CALL SCANB ; Any more parameters? | ||
| 563 | JNZ GETLIST ; If not end-of-line get list | ||
| 564 | POP DI ; Displacement of ENTER | ||
| 565 | POP ES ; Segment | ||
| 566 | GETROW: | ||
| 567 | CALL OUTDI ; Print address of entry | ||
| 568 | CALL BLANK ; Leave a space | ||
| 569 | CALL BLANK | ||
| 570 | GETBYTE: | ||
| 571 | MOV AL,ES:[DI] ; Get current value | ||
| 572 | CALL HEX ; And display it | ||
| 573 | PUTDOT: | ||
| 574 | MOV AL,"." | ||
| 575 | CALL OUT ; Prompt for new value | ||
| 576 | MOV CX,2 ; Max of 2 digits in new value | ||
| 577 | MOV DX,0 ; Intial new value | ||
| 578 | GETDIG: | ||
| 579 | CALL IN ; Get digit from user | ||
| 580 | MOV AH,AL ; Save | ||
| 581 | CALL HEXCHK ; Hex digit? | ||
| 582 | XCHG AH,AL ; Need original for echo | ||
| 583 | JC NOHEX ; If not, try special command | ||
| 584 | MOV DH,DL ; Rotate new value | ||
| 585 | MOV DL,AH ; And include new digit | ||
| 586 | LOOP GETDIG ; At most 2 digits | ||
| 587 | ; We have two digits, so all we will accept now is a command. | ||
| 588 | DWAIT: | ||
| 589 | CALL IN ; Get command character | ||
| 590 | NOHEX: | ||
| 591 | CMP AL,8 ; Backspace | ||
| 592 | JZ BS | ||
| 593 | CMP AL,7FH ; RUBOUT | ||
| 594 | JZ RUB | ||
| 595 | CMP AL,"-" ; Back CLDto previous address | ||
| 596 | JZ PREV | ||
| 597 | CMP AL,13 ; All done with command? | ||
| 598 | JZ EOL | ||
| 599 | CMP AL," " ; Go to next address | ||
| 600 | JZ NEXT | ||
| 601 | MOV AL,8 | ||
| 602 | CALL OUT ; Back CLDover illegal character | ||
| 603 | CALL BACKUP | ||
| 604 | JCXZ DWAIT | ||
| 605 | JMP SHORT GETDIG | ||
| 606 | |||
| 607 | RUB: | ||
| 608 | MOV AL,8 | ||
| 609 | CALL OUT | ||
| 610 | BS: | ||
| 611 | CMP CL,2 ; CX=2 means nothing typed yet | ||
| 612 | JZ PUTDOT ; Put back the dot we backed CLDover | ||
| 613 | INC CL ; Accept one more character | ||
| 614 | MOV DL,DH ; Rotate out last digit | ||
| 615 | MOV DH,CH ; Zero this digit | ||
| 616 | CALL BACKUP ; Physical backspace | ||
| 617 | JMP SHORT GETDIG ; Get more digits | ||
| 618 | |||
| 619 | ; If new value has been entered, convert it to binary and | ||
| 620 | ; put into memory. Always bump pointer to next location | ||
| 621 | |||
| 622 | STORE: | ||
| 623 | CMP CL,2 ; CX=2 means nothing typed yet | ||
| 624 | JZ NOSTO ; So no new value to store | ||
| 625 | ; Rotate DH left 4 bits to combine with DL and make a byte value | ||
| 626 | PUSH CX | ||
| 627 | MOV CL,4 | ||
| 628 | SHL DH,CL | ||
| 629 | POP CX | ||
| 630 | OR DL,DH ; Hex is now converted to binary | ||
| 631 | MOV ES:[DI],DL ; Store new value | ||
| 632 | NOSTO: | ||
| 633 | INC DI ; Prepare for next location | ||
| 634 | RET | ||
| 635 | NEXT: | ||
| 636 | CALL STORE ; Enter new value | ||
| 637 | INC CX ; Leave a space plus two for | ||
| 638 | INC CX ; each digit not entered | ||
| 639 | CALL TAB | ||
| 640 | MOV AX,DI ; Next memory address | ||
| 641 | AND AL,7 ; Check for 8-byte boundary | ||
| 642 | JNZ GETBYTE ; Take 8 per line | ||
| 643 | NEWROW: | ||
| 644 | CALL CRLF ; Terminate line | ||
| 645 | JMP GETROW ; Print address on new line | ||
| 646 | PREV: | ||
| 647 | CALL STORE ; Enter the new value | ||
| 648 | ; DI has been bumped to next byte. Drop it 2 to go to previous addr | ||
| 649 | DEC DI | ||
| 650 | DEC DI | ||
| 651 | JMP SHORT NEWROW ; Terminate line after backing CLD | ||
| 652 | |||
| 653 | EOL: | ||
| 654 | CALL STORE ; Enter the new value | ||
| 655 | JMP CRLF ; CR/LF and terminate | ||
| 656 | |||
| 657 | ; Console input of single character | ||
| 658 | |||
| 659 | IF SYSVER | ||
| 660 | IN: | ||
| 661 | PUSH DS | ||
| 662 | PUSH SI | ||
| 663 | LDS SI,CS:[CIN] | ||
| 664 | MOV AH,4 | ||
| 665 | CALL DEVIOCALL | ||
| 666 | POP SI | ||
| 667 | POP DS | ||
| 668 | CMP AL,3 | ||
| 669 | JNZ NOTCNTC | ||
| 670 | INT 23H | ||
| 671 | NOTCNTC: | ||
| 672 | CMP AL,'P'-'@' | ||
| 673 | JZ PRINTON | ||
| 674 | CMP AL,'N'-'@' | ||
| 675 | JZ PRINTOFF | ||
| 676 | CALL OUT | ||
| 677 | RET | ||
| 678 | |||
| 679 | PRINTOFF: | ||
| 680 | PRINTON: | ||
| 681 | NOT [PFLAG] | ||
| 682 | JMP SHORT IN | ||
| 683 | |||
| 684 | ELSE | ||
| 685 | |||
| 686 | IN: | ||
| 687 | MOV AH,1 | ||
| 688 | INT 21H | ||
| 689 | RET | ||
| 690 | ENDIF | ||
| 691 | |||
| 692 | CODE ENDS | ||
| 693 | END DEBCOM1 | ||
| 694 | |||