DEV Community

Charles Anthony
Charles Anthony

Posted on

2024-01-29 Debugging ZIP

I added some code to the OpenSIMH Altairz80 simulator to track memory access; for each byte of memory, it tracks if the byte was executed by the CPU, if the byte was an instruction operand, if the byte was read and if it was written. At the end of execution, the simulator writes the data out to a file. I then wrote a program that merged that data into the ZIP assembly listing, giving me a coverage map; I can see exactly which bits of code was executed in a run, and which were skipped.

As an example:

---- 00cf                          
  X  00cf 3a 00 01              _patch: ld      a,(s_mode)      ; get mode variable
  X  00d2 a7                            and     a               ; is it zero (execute)?
  X  00d3 ca 11 00                      jp      z,_abort        ; if so, restart
     00d6 d5                            push    de              ; else save message address
     00d7 2a 0e 01                      ld      hl,(s_current)  ; get vocabulary address
     00da 5e                            ld      e,(hl)          ; it points to the latest
     00db 23                            inc     hl              ;   entry, which was aborted
Enter fullscreen mode Exit fullscreen mode

The “X”es indicate that the first 3 lines of “_patch” were executed, but it always took the “wasn’t compiling” path.

And for the case of compiled words:

R    0744 01 ..                 db      1,"'  "
R    0748 b2 06         L_0004: dw      L_0003-4
R    074a 49 00         tick:   dw      p_colon
R    074c 92 0c                 dw      aspace  ; get the seperator
R    074e ca 13                 dw      token   ; scan the next token
R    0750 11 0e                 dw      context ; contect address
R    0752 f2 0b                 dw      at      ; contains vocabulary address
R    0754 f2 0b                 dw      at      ; contains the latest entry
R    0756 2c 13                 dw      search  ; search the vocabulary
R    0758 40 08                 dw      p_if    ; if false, found; otherwise
R    075a 0a                            db      tick1-$
     075b 03 10                 dw      entry   ; get latest current
     075d 2c 13                 dw      search  ; search current
     075f 40 08                 dw      p_if    ; if false, found; otherwise
     0761 03                            db      tick1-$
     0762 c0 12                 dw      question        ; echo token and ?
R    0764 31 00         tick1:  dw      psemi
Enter fullscreen mode Exit fullscreen mode

Here we see that the “‘“ keyword was executed; the “R” meaning the leading byte was read, in this case by the inner interpreter’s execution of the word. We also see that every time it was executed, it found the word in the CONTEXT vocabulary and never searched the CURRENT vocabulary.

Armed with this, I started writing an expect script that feeds input to ZIP, collecting and reporting the code coverage data.

I run the script, examine the coverage report and add new tests to the script that exercise unused code paths.

Top comments (0)