Log inRegister an accountBrowse CSDbHelp & documentationFacts & StatisticsThe forumsAvailable RSS-feeds on CSDbSupport CSDb Commodore 64 Scene Database
You are not logged in - nap
CSDb User Forums


Forums > C64 Coding > 6502 Static Analyser
2016-08-07 15:53
oziphantom

Registered: Oct 2014
Posts: 490
6502 Static Analyser

I've been working on a python script that I can run over 64tass's output to help me track bugs. At the moment it has the concept of a function, trashing a register or variable or modifying it. This then allows me to put in commands to verify that a function does not trash something.
pressA	
;&&trashes a,x,y,Pointer1,Pointer1+1,Pointer2,Pointer2+1
;&&modifies CursorX
	lda CursorX	
	beq KeyboardRoutine._exitPLA
	clc 
	adc #24
	tay
	jsr restoreVerticalDigitsBar ;&&preserve y
	dey
	jsr setVerticalDigitsBarToCurrent	
	dec CursorX
	rts

So here the system knows what is trashed. What is modified and assets that `restoreVerticalDigitsBar` does not trash or modify y.
When I wrote `restoreVerticalDigitsBar` it didn't but at some point I might add a feature, re factor the code to save a clock or so, and then trash y, which will give me a really hard to track down bug. Here the Build will catch and error for me.

The system will parse the code and report anything that is trashed that is not reported. It is a little annoying in that a parent function must also list everything its child functions trash, but this keeps it simple and allows you to see the whole tree when you look at just one function. The script also spits out a single HTML file which kind of acts like documentation. It will list name, address, size, what it calls,trashes and modifies. Handy for when you need to look up a function in the Win Vice debugger.

What else do you think would be useful?
 
... 1 post hidden. Click here to view all posts....
 
2016-08-07 18:36
soci

Registered: Sep 2003
Posts: 480
This test framework adds some extra code through macros and needs the output to be executed to give results. So 64spec is hardly static.

Was this used by the author on a real world program beyond writing the tests to test itself? Or it's just a proof of concept that it can be done. I'm not sure that it's all that practical until I see it in actual use.

I know at least that oziphantom is eating his own dog food. It's quite light on the amount of instrumentation needed, only some special comments at the right places.
2016-08-07 18:59
Oswald

Registered: Apr 2002
Posts: 5094
anyone has a script for adding breakpoints via comments, exports labels to vice etc ?
2016-08-07 19:32
soci

Registered: Sep 2003
Posts: 480
VICE labels can be had with "--vice-labels --labels=file.l".

I'd create source defined breakpoints using a specially named labels instead of a comments. Example Makefile fragment for compiling and starting VICE with breakpoint(s) set:
64tass -a -B $< -o $@ -L $@.dasm --vice-labels -l $@.l
sed -i 's/^al \([^ ]*\) .*breakpoint/break \1/' $@.l
x64 -moncommands $@.l -autostartprgmode 1 -autostart-warp +truedrive +cart $@
The sed script replaces any "al" line containing "breakpoint" in the label's name with a "break" command. The result looks like this:
...
al 9c7 .xp1
break 80e
al 956 .a1
...
Something similar could be done on windows as well using gnuwin32 sed or by other means.

But this is slightly off topic.
2016-08-07 20:43
Skate

Registered: Jul 2003
Posts: 494
@soci: win10 now has a built in ubuntu bash. from now on forget about windows builds, we can now directly use original linux sources. finally... :)
2016-08-07 23:07
Stone

Registered: Oct 2006
Posts: 172
This is outside the scope of what OP is talking about, but one thing that would be really neat is assertions implemented not as generated assembly code, but as breakpoint handlers in an emulator. Example:
getchar:
           ldy #$00
           lda (zp), y
           ASSERT(A < $80)
           rts

The assembler (or preprocessor) would generate a breakpoint at the ASSERT line and a corresponding breakpoint handler which is evaluated by the emulator each time the breakpoint is hit, but only stops execution when the assertion fails.

The great benefit of this is of course that the generated assembly code is exactly the same, whether assertions are enabled or not. Timing and codesize are completely unaffected.
2016-08-08 07:08
oziphantom

Registered: Oct 2014
Posts: 490
For getting 64tass labels loaded into vice.
You can use the --vicelables option but this only gets you the global and none of the locals which makes debugging functions harder. Also you don't get the members of structs just the first one.

I use this to build ( Relaunched64 script )
64tass.exe -a SOURCEFILE -o OUTFILE  --no-caret-diag --dump-labels -l SOURCENAME.tass -D BDD=0  -D CRT=0  -L SOURCENAME.list --verbose-list
cscript D:\pathstuff\dumpToVice.vbs SOURCENAME.tass SOURCENAME.vice
D:\emulation\WinVICE-2.4-x86\x64 -autostart  SOURCENAME.prg +confirmexit -reu -reusize 128 -moncommands SOURCENAME.vice


Where dumpToVice.vbs is
set args = WScript.Arguments
num = args.Count

Dim objFS, objFile
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objFile = objFS.CreateTextFile(args.Item(1),True)
Set inFile = objFS.OpenTextFile(args.Item(0))

' D:\GitHub\Qwack64\qwak.asm:1627:1: CollisionBoxesW = $1067

Do While Not inFile.AtEndOfStream
     blah = inFile.ReadLine()
     tokens = Split(blah,":")
     'tokens(0) = D
     'tokens(1) = file
     'tokens(2) = line
     'tokens(3) = char
     'tokens(4) = Thing = X
     If( InStr(tokens(1), "structs") = 0 ) Then
         If( InStr(tokens(0), "command line") = 0 ) Then
           If( InStr(blah, ":=" ) = 0 ) Then
               label = LTrim(tokens(4))
               If( Left(label,1) = "k" ) Then
                   'WScript.Echo label
                   secondChar = Mid(label,2,1)
                   If( LCase(secondChar) = secondChar ) Then
                      writeLine(label)
                   End IF
               Else
                   writeLine(label)
               End If
               'If( InStr(tokens(4), "=") > 0 ) then objFile.WriteLine (blah & "; dummy")
          End If
        End If
    Else
          label = LTrim(tokens(4))
          If( Left(label,1) = "s" ) Then
                   'WScript.Echo label
             secondChar = Mid(label,2,1)
             If( LCase(secondChar) = secondChar ) Then
                 writeLine(label)
             End IF
          Else
              writeLine(label)
          End If

    End If
Loop

Sub writeLine(label)
    parts = Split(label,"=")
    name = Replace(Trim(parts(0)),".","_")
    addr = Trim(parts(1))
    If (InStr(addr,"$") = 0 ) Then
       addr = "$"+Hex(addr)
    End If
    objFile.WriteLine("al "+addr+" ."+name)
End Sub


This way code like
convert2PuzzleRowsTo4_4
;&&trashes a,x,y,ZPTemp1,ZPTemp2,ZPTemp3,ZPTemp4,ZPTemp5,Pointer3
	#STAB ZPTemp6,ZPTemp4
_4lineLoop
	#STAB ZPTemp7,ZPTemp3
_wordLoop
	ldy #3
	lda PuzzleBuffer,x
	sta ZPTemp5
_byteLoop

will export
convert2PuzzleRowsTo4_4
convert2PuzzleRowsTo4_4__4lineLoop
convert2PuzzleRowsTo4_4__wordLoop
convert2PuzzleRowsTo4_4__byteLoop
into the labels for VICE
And
sGameData .struct 
lives .byte ?
score .byte ?,?,?,?,?,?
high .byte ?,?,?,?,?,?
currLevel .byte ?
.ends

GameData dStruct sGameData;

will export
GameData_lives
GameData_score
GameData_high
GameData_currLevel

For asserts and other testing I suggest MartinPipers's BDD6502. This lets you make some test scripts fairly easily to test your 6502 logic. It does not emulate a 64, just a 6502. So you can't check that it interrupts on Clock 5 of Raster line 37, there is no VIC. But you can ask it to check the state of a register or status flags to "assert" that a value is what you expect or not something.

I added some extra opcodes to it, which replace the illegal ops ( which it doesn't support )
PAT .macro 
	.byte $02
.endm
PXT .macro 
	.byte $12
.endm
PYT .macro 
	.byte $22
.endm
TTA .macro 
	.byte $32
.endm
TTX .macro 
	.byte $42
.endm
TTY .macro 
	.byte $52
.endm
INR .macro 
	.byte $62
.endm

PAT,PXT,PYT pushes A/X/Y onto an internal testing stack
TTA,TTX,TTY compares the current A/X/Y to the value on the testing stack. Thus allowing you to assert that A,X,Y are unchanged. Something my new SA mostly does, but it can't handle all cases.
INR = ignore return, this is for when you do an RTS to perform a JMP ( ) and don't want the system to make a new "test stack frame"
I does try to run at 1Mhz, but it will do all of an opcode then wait that many clocks. Which for the purposes of testing the 6502 logic is pointless, so I added an Overclocked 6502 option which runs as fast as it can. So my tests take 5 seconds and not 80.
BDD6502 takes labels in ACME format not Tass format. While I could modify it to take the RAM Tass, I already worked around it using this TASStoACME format. It takes the verbose format as above to give all locals, and struct members.
set args = WScript.Arguments
num = args.Count

Dim objFS, objFile
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objFile = objFS.CreateTextFile(args.Item(1),True)
Set inFile = objFS.OpenTextFile(args.Item(0))

' D:\GitHub\Qwack64\qwak.asm:1627:1: CollisionBoxesW = $1067

Do While Not inFile.AtEndOfStream
     blah = inFile.ReadLine()
     tokens = Split(blah,":")
     'tokens(0) = D
     'tokens(1) = file
     'tokens(2) = line
     'tokens(3) = char
     'tokens(4) = Thing = X
     If( InStr(tokens(1), "structs") = 0 ) Then
         If( InStr(tokens(0), "command line") = 0 ) Then
           If( InStr(blah, ":=" ) = 0 ) Then
               label = LTrim(tokens(4))
               If( Left(label,1) = "k" ) Then
                   'WScript.Echo label
                   secondChar = Mid(label,2,1)
                   If( LCase(secondChar) = secondChar ) Then
                      writeLine(label)
                   End IF
               Else
                   writeLine(label)
               End If
               'If( InStr(tokens(4), "=") > 0 ) then objFile.WriteLine (blah & "; dummy")
          End If
        End If
    Else
          label = LTrim(tokens(4))
          If( Left(label,1) = "s" ) Then
                   'WScript.Echo label
             secondChar = Mid(label,2,1)
             If( LCase(secondChar) = secondChar ) Then
                 writeLine(label)
             End IF
          Else
              writeLine(label)
          End If

    End If
Loop

Sub writeLine(label)
    parts = Split(label,"=")
    name = Replace(Trim(parts(0)),".","_")
    addr = Trim(parts(1))
    If (InStr(addr,"$") = 0 ) Then
       addr = "$"+Hex(addr)
    End If
    objFile.WriteLine(name + "="+addr+"; dummy")
End Sub
2016-08-08 07:35
soci

Registered: Sep 2003
Posts: 480
Quoting oziphantom
For getting 64tass labels loaded into vice.
You can use the --vicelables option but this only gets you the global and none of the locals which makes debugging functions harder. Also you don't get the members of structs just the first one.


This was so for a long time but this limitation was fixed in the last release:
https://sourceforge.net/p/tass64/news/2016/07/64tass-1521228/

"* Scoped variables are now output in VICE labels
Now scoped variables are included in VICE listing, which can help debugging a lot."


Due to a VICE parsing limitation a colon is used for separation. I've patched VICE to accept dots as well, and hope to change the output to dots someday once the update propagates sufficiently.

Quoting Stein
The assembler (or preprocessor) would generate a breakpoint at the ASSERT line and a corresponding breakpoint handler which is evaluated by the emulator each time the breakpoint is hit, but only stops execution when the assertion fails.


Interesting idea, reminds me to think about another postponed feature which could be used to do something like this.
2016-08-08 08:14
JackAsser

Registered: Jun 2002
Posts: 2014
Quote: This is outside the scope of what OP is talking about, but one thing that would be really neat is assertions implemented not as generated assembly code, but as breakpoint handlers in an emulator. Example:
getchar:
           ldy #$00
           lda (zp), y
           ASSERT(A < $80)
           rts

The assembler (or preprocessor) would generate a breakpoint at the ASSERT line and a corresponding breakpoint handler which is evaluated by the emulator each time the breakpoint is hit, but only stops execution when the assertion fails.

The great benefit of this is of course that the generated assembly code is exactly the same, whether assertions are enabled or not. Timing and codesize are completely unaffected.


help cond

Syntax: condition <checknum> if <cond_expr>
Abbreviation: cond

Each time the specified checkpoint is examined, the condition is
evaluated. If it evalutes to true, the checkpoint is activated.
Otherwise, it is ignored. If registers are specified in the expression,
the values used are those at the time the checkpoint is examined, not
when the condition is set.
The condition can use registers (A, X, Y, PC, SP, FL and other cpu
specific registers (see manual)) and compare them (==, !=, <, >, <=, >=)
against other registers or constants.
Registers can be the registers of other devices; this is denoted by
a memspace prefix (i.e., c:, 8:, 9:, 10:, 11:
Examples: A == 0, X == Y, 8:X == X)


Just saying...
2016-08-08 08:46
oziphantom

Registered: Oct 2014
Posts: 490
using the verbose list option, you could put say
;&&assert (vice compatible condition here )
and then parse the listing and then append break XXXX (condtion) to a labels file? I've never been able to work out the Condition format properly, but I could try a quick test.

I've also thought about making a "protected memory" map.
So the SA spits out a bunch of
RAM,CODE, DATA, NoMansLand ranges.
CODE gets a LOAD and STORE break point put on it, to error if it is changed, DATA gets a break point put on it to make sure it is not incorectly ran, NoMansLand gets a Break,LOAD,STORE set on it as you code should not be touching it and if it is then it is a bug. RAM gets nothing set on it.
2016-08-08 10:36
Stone

Registered: Oct 2006
Posts: 172
Quoting JackAsser
help cond

Syntax: condition <checknum> if <cond_expr>
Abbreviation: cond
...

Just saying...

Yes, I'm aware of conditional breakpoints in vice.

TODO:
"The assembler (or preprocessor) would generate a breakpoint at the ASSERT line and a corresponding breakpoint handler"
Previous - 1 | 2 - Next
RefreshSubscribe to this thread:

You need to be logged in to post in the forum.

Search the forum:
Search   for   in  
All times are CET.
Search CSDb
Advanced
Users Online
Flashback
morphfrog
Knut Clausen/SHAPE/F..
Alakran_64
Broti/DT/KRN
Devia/Ancients
Paulko64
Guests online: 83
Top Demos
1 Next Level  (9.7)
2 13:37  (9.7)
3 Mojo  (9.7)
4 Coma Light 13  (9.6)
5 Edge of Disgrace  (9.6)
6 What Is The Matrix 2  (9.6)
7 The Demo Coder  (9.6)
8 Uncensored  (9.6)
9 Comaland 100%  (9.6)
10 Wonderland XIV  (9.6)
Top onefile Demos
1 Layers  (9.6)
2 No Listen  (9.6)
3 Cubic Dream  (9.6)
4 Party Elk 2  (9.6)
5 Copper Booze  (9.6)
6 Rainbow Connection  (9.5)
7 Dawnfall V1.1  (9.5)
8 Onscreen 5k  (9.5)
9 Morph  (9.5)
10 Libertongo  (9.5)
Top Groups
1 Performers  (9.3)
2 Booze Design  (9.3)
3 Oxyron  (9.3)
4 Triad  (9.3)
5 Censor Design  (9.3)
Top Swappers
1 Derbyshire Ram  (10)
2 Jerry  (9.8)
3 Violator  (9.7)
4 Acidchild  (9.7)
5 Cash  (9.6)

Home - Disclaimer
Copyright © No Name 2001-2024
Page generated in: 0.089 sec.