''[JM] 14 Nov 2012'' - After "[Playing Assembler]" a little bit, and looking at the [RS] comments that says: "Of course this is no real assembler. The memory model is constant-size instructions...", that just sounded like how the PIC microcontroller is arranged [http://en.wikipedia.org/wiki/PIC_micro#Code_space]<
>
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.<
>
Again, this is not quite ready yet, for example, the command
addwf chrix,w
was now written as
addwf chrix
This time, I hard-coded the W register as the destiny of the add result.
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.
======
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]}
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 "\ndump...prog memory"
foreach i [lsort -integer [array names mem]] {
puts [format "%04d %s" $i $mem($i)]
}
puts "\ndump...sym names"
foreach i [lsort [array names sym]] {
puts [format "%-10s: %04x" $i $sym($i)]
}
}
proc run {{pc 256}} {
puts "\nrun..."
#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
}
}
}
#----------------- "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 {
variable ram
set ::W [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 $value}
}
#-- Now testing:
asm::asm {
org 0 ; the canonical start address in PICs
movlw 0
movwf offset
movlw 32
movwf chrix
movlw 48
movwf FSR
movlw 16
movwf counter
WEER: movfw counter
addwf chrix
movwf INDF
;call puts
incf FSR
decfsz counter
goto weer
incf offset
incf chrix
end
}
asm::run 0
puts "\nRAM 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" $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 32
0003 MOVWF CHRIX
0004 MOVLW 48
0005 MOVWF FSR
0006 MOVLW 16
0007 MOVWF COUNTER
0008 MOVFW COUNTER
0009 ADDWF CHRIX
0010 MOVWF INDF
0011 INCF FSR
0012 DECFSZ COUNTER
0013 GOTO 8
0014 INCF OFFSET
0015 INCF CHRIX
dump...sym names
WEER : 0008
run...
RAM after run:
addr contents
---- --
0030: 30
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 %
<> Language | Tcl and other languages