Category : Assembly Language Source Code
Archive   : SIG8051.ZIP
Filename : DEBUG51.ASM

Output of file : DEBUG51.ASM contained in archive : SIG8051.ZIP

; This code is hereby released into the public domain and may be freely
; copied and distributed by provided the following notice is included:
; Copyright (c) 1988 by Axonn Corporation
; 101 West Robert E. Lee Blvd #402
; New Orleans, LA 70124
; All of the included code is exerpted from a functional and tested product
; developed by Axonn Corp., a research and development laboratory.
; Nevertheless, the code is supplied strictly as a public service and no
; responsibility for bugs can be assumed.

; During the development of an 87c751 based product at Axonn, we chose to
; use the product itself as the ideal testbed for development since,
; unfortunately, the microwatt hardware and real time aspects of our product
; made the use of an emulator inconvenient and this debugger resulted.
; The debugger has a few simple commands that allow user subroutines to be
; called, and their results examined. RAM locations can be examined and
; modified. While this falls rather short of a full-blown debugger, we found
; it quite convenient compared to logic analyzers and oscilliscopes for
; real time work. Those who desire more features and have memory to spare
; should find it easy to add them.

; The debugger utilizes two spare bits as a software serial port that
; allows the 87c751 to be connected to and debugged from a serial terminal (we
; used an AT-clone and Procomm). Only the minimum possible 87c751 resources
; were used so the debugger is quite compact and RAM efficient, naturally at
; the expense of fancy features. All port references are hard-coded because
; my assembler required it - sorry.
; Commands: C-all
calls the specified routine at the specified
; 16 bit address. The Acc, SP, and R0-R2 are
; printed on return from the routine.
; M-odify
modify consecutive RAM locations, each in turn
; until ANY invalid input is encountered (yes,
; this can be irritating).
is an
; 8-bit RAM address.
; D-ump
prints the contents of 16 RAM locations
; starting with the specified 8-bit address.
; V-ersion prints out the version of software in use. We
; use this to track versions of our application
; software after the security bits have been
; programmed.
; Serial Port Parameters: The serial port sends 8 bit data at 2400 baud with
; one start bit, one stop bit, and no parity. All
; timing is accomplished with software timing loops
; that assume a 16 Mhz crystal. Adequate information
; is provided to allow simple accomodation of other
; clock speeds.
; General: No special hardware features of the 87c751 have been used, which
; should make the debugger portable to other 8051 family processors,
; as well as tolerant of most target system configurations.

; The most glaring omission is of a single-stepping function, one which I
; intended to implement, but found to be unnecessary. My plan was to jump to
; the target instruction, and set the timer for an immediate interrupt. The
; interrupt handler would finish the work. Such an implementation would
; naturally interfere with normal interrupt operation, and could thus be
; undesirable.
; Other possible conveniences:
; - Dumping of all registers upon subroutine exit
; - Permit calling of subroutines with specified register values
; These features can be easily added with minor changes as required.

; As a parting note, I wish to include a few suggestions on debugging
; techniques that I found helpful in my task.
; 1) Write independent subroutines that can be debugged individually.
; Call and debug those that you can with the C-all command.
; 2) use extra output port bits as signals when debugging real-time
; routines. I pulsed one port bit when a START bit was detected,
; another when the serial data was actually being sampled, and
; a third for the STOP bit.
; 3) use the putchr routine to print out a trail as your program
; executes, "a" at the first decision point, "b" at the second, etc.
; If serial output degrades your real-time operation, use the SIGNAL
; routine to the same end.
; Here's wishing all best luck,
; The Axonn Staff

crshcode equ 1

ramr0 equ 0 ;addresses of registers stored in ram
ramr1 equ 1
ramr2 equ 2

;-------------- Data --------------
org 3fh-8

crctmp ds 2 ;temporary for CRC16
ramchk ds 2 ;RAM check sequence used to ensure RAM integrity.
timeout ds 2 ;communications timer

;<<<<--------------------------- Main Program ---------------------------->>>>
sjmp main

ORG 0bh
ajmp timerint

ORG 28h
ajmp debug

; This is where the processor goes after reset
main: mov a,#(LOW debug8) ;place debug return address on the stack
push acc
mov a,#(HIGH debug8)
push acc

; ------------------------------------------------------
; ----------- Application Program goes here ------------
; This is where an application program should reside.
; ------------------------------------------------------

sjmp $
;===================== End of Main Program ========================

;- Debug -
; This primitive debugger allows the following operations:
; M-odify RAM location
; D-ump RAM
; C-all subroutine
; V-ersion

debug0: mov sp,#7
mov a,#(LOW debug8) ;place return address on the stack
push acc
mov a,#(HIGH debug8)
push acc

debug: acall putstr
db 10,13
db "debug>",0 ;prompt James with ">"
mov timeout, #0
mov timeout+1,#0
acall getc
anl a,#0dfh ;lower to uppercase
acall putc
cjne a,#"M",debug4

; If we arrive here, we have a -MODIFY- command
push ramr0
acall getaddr
jc debug2 ;if the address was bad, quit this command
mov r0,a
debug1: mov a,@r0
acall putsp ; ELSE print the contents of the next location
acall puthex
mov a,#"<" ;prompt for a new value to deposit
acall putc
acall getaddr ;input the new value, quit if it's invalid
jc debug2
mov @r0,a
inc r0
sjmp debug1

debug2: pop ramr0
ajmp debug7

; If we are here, we have a -CALL- command
debug4: cjne a,#"C",debug5
acall putsp ;get the address to call in DPTR.
acall getaddr
jc debug7 ;quit if address was bad
mov dph,a
acall getaddr
jc debug7 ;quit if address was bad
mov dpl,a
mov a,#(LOW debug8) ;place return address on the stack
push acc
mov a,#(HIGH debug8)
push acc
push dpl
push dph

; D-ump memory command. Print the hex form of 16 bytes.
debug5: cjne a,#"D",debug7a
acall getaddr
mov r0,a
mov r2,#8
debug6: acall putsp
mov a,@r0
acall puthex
inc r0
djnz r2, debug6
mov a,#"-"
acall putc

mov r2,#8
acall putsp
mov a,@r0
acall puthex
inc r0
djnz r2, debug61
ajmp debug

; This is where we handle invalid inputs
debug7: mov a,#"?"
acall putc
ajmp debug

cjne a,#"V",debug7
acall putstr
db 13,10
db "V1.00 (c) 1988 Axonn Corp., New Orleans, LA 70124"
db " edited Tue 11-01-88 jda.",13,10,0
ajmp debug

; This is where the processor returns when the debugger regains control.
debug8: push sp ;show the registers on exit
push ramr2
push ramr1
push ramr0
push acc
push psw
acall putstr
db 10,13, " Stopped. ",0
pop psw
jnc debug9
mov a,#"C"
acall putc
acall putsp

debug9: acall putstr ;Accumulator
db "A=",0
pop acc
acall puthex

acall putstr
db " R0=",0 ;R0
pop acc
acall puthex

acall putstr
db " R1=",0 ;R1
pop acc
acall puthex

acall putstr
db " R2=",0 ;R2
pop acc
acall puthex

acall putstr
db " SP=",0 ;SP
pop acc
acall puthex

mov sp,#8 ;make sure the Stack Pointer and register select bits
mov psw,#0 ;are in a reasonable state.
ajmp debug

downXf: setb c
ret ;download exit with failure

downX: clr c
ret ;download exit
;----- end of Download -----

;%%%%%%%%%%%%%%%%%%%%%%%%%%%% Various Subroutines %%%%%%%%%%%%%%%%%%%%%%%%%%

;-- crc16 --
; computes crc given the start address in R1 and the length in R2. R0 should
;point to the desired seed value (permitting chaining of crc16 computations).
; INPUT: r0=sequence address, r1=start address, r2=length
; OUTPUT: crctmp
; Polynomial: x^16 + x^15 + x^2 + 1 (1100 0000 0000 0101)
mov crctmp,@r0 ;transfer sequence to crctmp
inc r0
mov crctmp+1,@r0

; get the next byte to be CRC'd
crc002: mov a,@r1
xrl crctmp+1,a
mov r3,#8 ;r3 will count bits

; accumulate each bit into the CRC
crc004: clr c
mov a,crctmp
rrc a
mov crctmp,a
mov a,crctmp+1
rrc a
mov crctmp+1,a
jnc crc008

xrl crctmp, #0a0h ;XOR polynomial into CRC (bit reversed)
xrl crctmp+1,#01h

djnz r3, crc004 ;we must do all 8 bits.

; here we have finished a byte
inc r1 ;point to the next byte
djnz r2,crc002 ;if not all bytes CRC'd, then loop.

; move the temporary to the desired sequence location
mov @r0,crctmp+1
dec r0
mov @r0,crctmp
; ----- End of CRC16 ------

;ok -- getaddr --
;Input an 8 bit hex number, returned in A.
mov timeout,#0
mov timeout+1,#0
acall getc
acall putc
acall hexbin
jc getadX
swap a
mov r2,a
acall getc
acall putc
acall hexbin
orl a,r2
getadX: ret

; ----- getc -----
; Get a single character from the programming terminal.
; Baud rate is set at 2400 baud for a 16Mhz crystal.
; INPUT: timeout in 18uS units @ 16Mhz. (0=no timeout)
getc: push ramr0
push ramr1
setb p3.5 ;enable serial in
mov a,timeout
mov r1,timeout
orl a,timeout+1 ;IF timeout <> 0
jnz getc0 ; THEN use the timed input routine

getc0a: jb p3.5,getc0a ;wait for start bit, no timeout

getc0: jnb p3.5,getc0d ;2 Timed Input Procedure
nop ;1
mov r0,#4 ;1
getc0c: jnb p3.5,getc0d
djnz r0,getc0c ;16 = 4x4
mov a,timeout+1 ;1
dec timeout+1 ;1
jnz getc0 ;2
djnz r1,getc0
setb c ;set the carry for timeout error
sjmp getcX ;EXIT

getc0d: mov r0,#206 ;206 * 4 * 750ns = 1+1/2 bit @ 2400 baud
getc01: nop
djnz r0,getc01

; now we should be in the middle of the first bit
mov r0,#8
getc02: mov c,p3.5
rrc a
acall wait0
djnz r0,getc02
mov c,p3.5 ;if stop bit is bad, set the carry
cpl c
getcX: pop ramr1
pop ramr0

;ok -- hexbin --
;convert an ASCII hex digit in A into its' binary equivalent.
;C flag set indicates invalid hex digit.

hexbin: clr c
subb a,#"A" ;lower to uppercase conversion
jc hex01
anl a,#0dfh
hex01: add a,#"A"

;the char is now uppercase and/or numeric
clr c
subb a,#"0" ;IF char < "0"
jc hexbiX ; THEN exit
subb a,#10 ;IF char <= "9"
jc hex03 ; THEN it is numeric

;if we get here, the char may be alphabetic
add a,#10
subb a,#("A"-"0") ;IF "9" < char < "A"
jc hexbiX ; THEN error
subb a,#6
jc hex02 ;IF "F" < char,
setb c ; THEN error
sjmp hexbiX

hex02: add a,#6
hex03: add a,#10
clr c
hexbiX: ret
;---- end of Hexbin ----

;ok ----- Crlf -----
; Send a onthe serial programming port
crlf: push acc
mov a,#0dh
acall putc
mov a,#0ah
acall putc
pop acc

;ok ----- PutHex -----
; Prints A in hex ASCII on the serial programming port.
puthex: push acc
swap a
acall puth1
pop acc
puth1: anl a,#15
add a,#0f6h ;cmp a,9
jnc puth2
add a,#7
puth2: add a,#3ah
acall putc

;ok ----- putc -----
; Output one character on the serial programming port.
putc: push acc
push ramr0
push ramr1
mov r0,#9 ;8 bits + stop bit
clr p3.6 ;send start bit
setb c ;stop bit=1
acall wait0
putc02: rrc a
mov p3.6,c
acall wait0
djnz r0,putc02
pop ramr1
pop ramr0
pop acc

;ok-- putsp --
; Print a space
putsp: push acc
mov a,#" "
acall putc
pop acc

;-- putstr --
; Print the zero-delimited string that follows the call to this routine.
; Example:
; ACALL putstr
; DB "Hi Mr. Rhinocerous",0

putstr: pop dph
pop dpl
push acc
mov a,#0
movc a,@a+dptr
jz putstrX
acall putc
mov a,dpl
add a,#1
mov dpl,a
jnc putstr1
inc dph
sjmp putstr1

inc dpl
mov a,dpl
jnz putstrX1
inc dph
pop acc
push dpl
push dph

;----- signal ----
; This routine zips out the code in the accumulator in serial fashion using
; the bits p3.3, p3.4. This is a useful way of examining a process in real
; time with the use of an oscilliscope.
; INPUT: Acc
; OUTPUT: p3.3 = data
; p3.4 = clock
signal: push ramr2
anl p3,#(NOT 18h) ;clear our two signalling bits
mov r2,#8
signl1: rlc a
mov p3.3,c
setb p3.4
clr p3.4
djnz r2,signl1
pop ramr2
orl p3,#18h ;leave the bits high when done

;----- timerint -----
; Used for debugging.

;ok ----- wait0 -----
;delay one bit time @ 2400 baud.
wait0: mov r1,#137
wait01: nop
djnz r1,wait01

  3 Responses to “Category : Assembly Language Source Code
Archive   : SIG8051.ZIP
Filename : DEBUG51.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: