Tip: debugging trick that helped me

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

Tip: debugging trick that helped me

The111
I found project 8 to be the most difficult so far (by a large margin), and when I was near completing it I found this cool trick.  One of the hardest parts about debugging it is that if you run the .vm file(s) in the VME, each "step" does not correspond with one step in your ASM file.  So if you have the ASM file open in the CPU emulator, and the .vm file open in the VME, you have to click "step" many times in CPU emu (i.e. anywhere from 5x - 50x) to match every single "step" you click in the VME (the reason you'd want to keep the CPU emu and VME in sync is to watch all your RAM locations and see where your problem is occurring).

So, the trick is that you have your asmWriter program add something like this at the beginning of every new .vm line that it translates:

@7777
M=0
M=1

The idea is that 7777 is a RAM location you know is not being used for anything.  Now in the CPU emulator you can set RAM[7777]=0 as a debug breakpoint, and every time you hit the "fast forward" button in the CPU emu, it corresponds with one "step" in the VME.  Helped me a lot, hope it helps someone else!
Reply | Threaded
Open this post in threaded view
|

Re: Tip: debugging trick that helped me

cadet1620
Administrator
This is a very clever idea!

I agree that the VM is the hardest project in the book. There are many new concepts and you need to learn the Hack architecture and instruction set in great detail.

I learned programming in the days of mainframes, punch cards, and line printers. By reflex, I wrote my Hack assembler to generate a listing file:

             // This file is part of the materials accompanying the book
             // "The Elements of Computing Systems" by Nisan and Schocken,
             // MIT Press. Book site: www.idc.ac.il/tecs
             // File name: projects/06/max/Max.asm

             // Computes M[2] = max(M[0], M[1])  where M stands for RAM
    0     0     @0
    1  FC10     D=M              // D=first number
    2     1     @1
    3  F4D0     D=D-M            // D=first number - second number
    4    10     @OUTPUT_FIRST
    5  E301     D;JGT            // if D>0 (first is greater) goto output_first
    ...
I have my VM translator write the VM source lines as comments in the ASM output. Armed with the listing file generated by assembling my VM output I could quickly find the generated code by address, and set breakpoints as needed.

It would have been much quicker to use your trick.

It might be handy to include the VM source line number to make it easier to relate ASM and VM code:

    @123    {line number}
    @7777
    M=0
    M=1 

--Mark

Reply | Threaded
Open this post in threaded view
|

Re: Tip: debugging trick that helped me

ybakos
In reply to this post by The111
Nice, thanks for sharing that.
Reply | Threaded
Open this post in threaded view
|

Re: Tip: debugging trick that helped me

The111
This post was updated on .
In reply to this post by cadet1620

It might be handy to include the VM source line number to make it easier to relate ASM and VM code:

Yeah, that is a good idea too. I did something similar but not quite as nice with actual line numbers. Excerpt from my StaticsTest.asm file:

// ************* initialize stack pointer *************
@256
D=A
@SP
M=D
// ************* call Sys.init 0 *************
@7777
M=0
M=1
@LABEL_1
D=A
@SP
A=M
...
Though I like the look of your asm file, pretty nifty with the line numbers and hex codes all neatly aligned!

Also, if you're sure it's unused, then 255 can be used in place of 7777 and you will always be looking at the bottom of your stack (rather than have to scroll through 7000 lines to get back to the RAM that matters, since it focuses on a RAM location every time it modifies it).

Reply | Threaded
Open this post in threaded view
|

Re: Tip: debugging trick that helped me

aexpert999
Great!Thanks a lot!
Reply | Threaded
Open this post in threaded view
|

Re: Tip: debugging trick that helped me

Albert G
You can actually use a simpler technique. Just set a breakpoint on the value of A. So you just need one line to set a break point, for example:

@7777

So instead of setting a breakpoint when a specific RAM location gets a certain value, just set it when A gets a specific value. It is less intrusive (a single line per break point), and you do not get the "jumping" back and forth in the emulator.

Albert.
Reply | Threaded
Open this post in threaded view
|

Re: Tip: debugging trick that helped me

virote328
In reply to this post by The111
I developed a similar trick where after each vm command I would "@22222" at the end of each vm_command_to_ASM translation.

It helped me see where each vm command began and end.

plus, like the other guy said, you can set a break point whenever A = 22222.

Reply | Threaded
Open this post in threaded view
|

Re: Tip: debugging trick that helped me

Andrew Trefethen
In reply to this post by The111
Freaking genius! Once i found your advice, I solved my issue within 20 minutes. I was mishandling my static variables.
Reply | Threaded
Open this post in threaded view
|

Re: Tip: debugging trick that helped me

Lozminda
In reply to this post by virote328
I've been using something like this as a  temporary marker, to mark my asm code at a particular point:

D=D
D=D
D=D
D=D

Or some other harmless code (what ever stands out and doesn't have any operational effect)

and when this comes up on the CPUEmulator you know where you are as it where. Obvs this is only a temp. thing and should be removed from any final version.

As I say, everyone else’s ideas seem to be better.....
Reply | Threaded
Open this post in threaded view
|

Re: Tip: debugging trick that helped me

Lozminda
Ps

I've started using virote328's method, it's much better ! (ie using @22222, @22223 etc)
Reply | Threaded
Open this post in threaded view
|

Re: Tip: debugging trick that helped me

newtx1
This post was updated on .
In parallel with the output .ASM file, my VM translator creates a .VMOBJ that looks like this:
(example from the first few lines of BasicTest.vm)

// BasicTest.vm:7 push constant 10
000 : @30007   //  <-- break on A = 30007
001 : @10
002 : D=A
003 : @0
004 : AM=M+1
005 : A=A-1
006 : M=D
// BasicTest.vm:8 pop local 0
007 : @30008   //  <-- break on A = 30008
008 : @1
009 : D=M
010 : @popsaveaddr
011 : M=D
012 : @0
....  etc etc

You see:
// <VM filename>:<source file line #>  <text of VM source line>
<line number seen in CPU emulator> : @<incrementing break number>  // <help text>
<line #> : <ASM blob for this VM line>
<line #> : <ASM blob for this VM line>
.... etc etc

Break number increments per VM->ASM blob (aka each source VM line), so breaking on A=# will stop before that instruction blob is executed.  Just copy and paste the break number into the break window.

All of these variables are easy to track as you translate each line of VM source, ASM blob #, and output ASM line number.  You can match source code to VM lines as .ASM blob lines in the CPU emulator very quickly.

I set it up so my VM translator normally returns a .VMOBJ along with the .ASM object code, and a "--debug" flag turns on the break numbers.

You just have to make sure that your .VMOBJ and .ASM files are generated at the same time! :)

FYI: my version of the VMOBJ file is just a helper and can't be assembled by itself, unless you strip out the line numbers
Reply | Threaded
Open this post in threaded view
|

Re: Tip: debugging trick that helped me

WBahn
Administrator
The output of all of my tools embedded comments in the output code that the subsequent tools could access (if it was there) and was also human-readable. These comments gave put sufficient information into the final assembly file that you could actually reconstruct the source code (including comments) as well as see which address each assembly instruction ended up at. This made both debugging the tools and the code written using them MUCH easier. Organizing it so that it wasn't a mish-mash took some thought, but the process is so inherently hierarchical that it wasn't that bad.