So I took a section of a PIC's working code (a loop that fills a RAM buffer for a later transfer to a LCD) and tweak Playing Assembler with a few of the PIC's instruction set.
the example shows a RAM buffer (from 30H to 3FH) filled with values descending from 30H to 21H. The real thing in hardware shows all the possible charactes a LCD can display.[2]
console show namespace eval asm { proc asm body { variable mem catch {unset mem} ;# good for repeated sourcing foreach line [split $body \n] { foreach i {label op args} {set $i ""} regexp {([^;]*);} $line -> line ;# strip off comments regexp {^ *(([A-Z0-9]+):)? *([A-Z]*) +(.*)} [string toupper $line]\ -> - label op args # puts label=$label,op=$op,args=$args if {$label!=""} {set sym($label) $PC} if {$op==""} continue if {$op=="DB"} {set mem($PC) [convertHex $args]; incr PC; continue} if {$op=="EQU"} {set sym($label) [convertHex $args]; continue} if {$op=="ORG"} { set PC [convertHex $args] continue } regsub -all ", *" $args " " args ;# normalize commas set mem($PC) "$op $args" incr PC } substituteSymbols sym dump sym } proc convertHex s { set s [string trim $s] #tk_messageBox -message $s if [regexp {^H'([0-9A-F]+)'$} $s -> s] {set s [expr 0x$s]} if [regexp {^D'([0-9A-F]+)'$} $s -> s] {set s $s} set s } proc substituteSymbols {_sym} { variable mem upvar $_sym sym foreach i [array names mem] { set tmp [lindex $mem($i) 0] foreach j [lrange $mem($i) 1 end] { if {[array names sym $j]==$j} {set j $sym($j)} lappend tmp $j } set mem($i) $tmp } } proc dump {_sym} { variable mem variable ram upvar $_sym sym puts "\n dump...prog memory" foreach i [lsort -integer [array names mem]] { puts [format " %04d %s" $i $mem($i)] } puts "\n dump...sym names" foreach i [lsort [array names sym]] { puts [format " %-10s: %04x" $i $sym($i)] } } proc run {{pc 0}} { puts "\n running ASM program..." #incr pc -1 variable mem foreach i {A B C D E Z W} {set ::$i 0} #tk_messageBox -message "pc: $pc: $mem($pc)" while {$pc>=0} { incr pc #tk_messageBox -message "pc: $pc: $mem($pc)" if {[info exists mem($pc)]} { #puts "$mem($pc)\tA:$::A B:$::B C:$::C D:$::D E:$::E Z:$::Z" #tk_messageBox -message "$mem($pc)\tA:$::A B:$::B C:$::C D:$::D E:$::E Z:$::Z" eval $mem($pc) } else { break } } puts " ASM program ended..." } #----------------- "machine opcodes" implemented as procs proc SHOWRAM dummyNr { variable ram puts "---RAM dump" foreach i [lsort [array names ram]] { puts "$i: $ram($i)" } } proc ADDWF {adr dest} { variable ram if {$dest == "W"} { set ::W [expr $ram($adr) + $::W] } else { set ram($adr) [expr $ram($adr) + $::W] } } proc CALL {name} {[string tolower $name] $::W} proc GOTO adr { #tk_messageBox -message "GOTO $adr" uplevel 1 set pc [expr $adr - 1] } proc INCF adr { variable ram set ram($adr) [expr $ram($adr) + 1] } proc DECFSZ adr { variable ram set ram($adr) [expr $ram($adr) - 1] if {$ram($adr) == 0} {uplevel 1 set pc [expr [uplevel 1 set pc] +1]} } proc MOV {reg adr} {variable mem; set ::$reg $mem($adr)} proc MOVWF adr { variable ram if {$adr == "INDF"} { set fsrC $ram(FSR) set ram($fsrC) $::W } else { set ram($adr) $::W } } proc MOVFW adr { variable ram set ::W $ram($adr) } proc MVI {reg value} {set ::$reg $value} proc MOVLW value {set ::W [convertHex $value]} } #-- Now testing: asm::asm { org 0 ; the canonical start address in PICs movlw 0 movwf offset movlw H'20' movwf chrix movlw H'30' movwf FSR movlw D'16' movwf counter WEER: movfw counter addwf chrix,w movwf INDF ;call puts incf FSR decfsz counter goto weer incf offset incf chrix end } asm::run puts "\n RAM after run:" puts " addr contents" puts " ---- --" foreach i [lsort [array names asm::ram]] { #puts "$i [string is integer $i]" if [string is integer $i] { puts [format " %04x: %02x (%c)" $i $asm::ram($i) $asm::ram($i)] } else { puts [format " %-10s: %02x" $i $asm::ram($i)] } }When running the example, the outputs is:
dump...prog memory 0000 MOVLW 0 0001 MOVWF OFFSET 0002 MOVLW H'20' 0003 MOVWF CHRIX 0004 MOVLW H'30' 0005 MOVWF FSR 0006 MOVLW D'16' 0007 MOVWF COUNTER 0008 MOVFW COUNTER 0009 ADDWF CHRIX W 0010 MOVWF INDF 0011 INCF FSR 0012 DECFSZ COUNTER 0013 GOTO 8 0014 INCF OFFSET 0015 INCF CHRIX dump...sym names WEER : 0008 running ASM program... ASM program ended... RAM after run: addr contents ---- -- 0030: 30 (0) 0031: 2f (/) 0032: 2e (.) 0033: 2d (-) 0034: 2c (,) 0035: 2b (+) 0036: 2a (*) 0037: 29 ()) 0038: 28 (() 0039: 27 (') 003a: 26 (&) 003b: 25 (%) 003c: 24 ($) 003d: 23 (#) 003e: 22 (") 003f: 21 (!) CHRIX : 21 COUNTER : 00 FSR : 40 OFFSET : 01(code) 1 %
Jorge - 2012-11-15 16:57:13
- changed the ORG address to the canonical start address for PICs
- prepared the hex pattern for conversion to be H'nn'
- cleaned up the output to show RAM addresses in hex format also
Jorge - 2012-11-15 22:18:41
- the command addwf was fixed to properly use "d" as a switch to define if the result is to be stored in the file register itselt or the W register.
addwf chrix,w
- hex preffix was changed to H'nn' to follow MPLAB syntax (the well known 0x is also valid though not implemented here yet)
- default ORG address in run proc was set to 0
- the corresponding char is shown to illustrate which set of symbols are going to be displayed on LCD
Jorge - 2014-01-30 23:01:01I was just looking at simavr (for AVR devices, not PIC though) and thought it could be great if calling the simulation could be done from Tcl (Replacing Glut)...we could then construct nice GUI around that simulator.http://makezineblog.files.wordpress.com/2009/12/simavr_avr_simulator.jpg?w=900&h=603
Jorge - 2014-11-10 02:23:09I think I will try gluttk
Jorge - 2016-1-4See alsohttp://www.microcontrollerjs.com/