''[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 working code (a loop that fills a RAM buffer for a later transfer to a LCD), again, this is not quite ready yet, for example, the command
addwf chrix,w
was now written as
addwf chrix
implying that the destiny is the W register
the example shows a RAM buffer (from 48d to 63d) 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]
if [regexp {^([0-9A-F]+)H$} [string trim $s] -> s] {set s [expr 0x$s]}
set 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 "dump..."
foreach i [lsort -integer [array names mem]] {
puts [format "%04d %s" $i $mem($i)]
}
foreach i [lsort [array names sym]] {
puts [format "%-10s: %04x" $i $sym($i)]
}
}
proc run {{pc 256}} {
puts "run..."
incr pc -1
variable mem
foreach i {A B C D E Z W} {set ::$i 0}
while {$pc>=0} {
incr 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)
#incr pc
}
}
#----------------- "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 {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 100 ; the canonical start address in CP/M
goto START ; idiomatic: get over the initial variable(s)
DONE: equ 0 ; warm start in CP/M ;-)
MAX: equ 5
INCR: db 2 ; a variable (though we won't vary it)
;; here we go...
START: 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
goto DONE
end
}
asm::run 100
puts "RAM after run:"
foreach i [lsort [array names asm::ram]] {
puts [format "%-10s: %04x" $i $asm::ram($i)]
}
When running the example, the outputs is:
label=,op=,args=
label=,op=ORG,args=100
label=,op=GOTO,args=START
label=DONE,op=EQU,args=0
label=MAX,op=EQU,args=5
label=INCR,op=DB,args=2
label=,op=,args=
label=START,op=MOVLW,args=0
label=,op=MOVWF,args=OFFSET
label=,op=MOVLW,args=32
label=,op=MOVWF,args=CHRIX
label=,op=MOVLW,args=48
label=,op=MOVWF,args=FSR
label=,op=MOVLW,args=16
label=,op=MOVWF,args=COUNTER
label=WEER,op=MOVFW,args=COUNTER
label=,op=ADDWF,args=CHRIX
label=,op=MOVWF,args=INDF
label=,op=,args=
label=,op=INCF,args=FSR
label=,op=DECFSZ,args=COUNTER
label=,op=GOTO,args=WEER
label=,op=INCF,args=OFFSET
label=,op=INCF,args=CHRIX
label=,op=GOTO,args=DONE
label=,op=,args=END
label=,op=,args=
dump...
0100 GOTO 102
0101 2
0102 MOVLW 0
0103 MOVWF OFFSET
0104 MOVLW 32
0105 MOVWF CHRIX
0106 MOVLW 48
0107 MOVWF FSR
0108 MOVLW 16
0109 MOVWF COUNTER
0110 MOVFW COUNTER
0111 ADDWF CHRIX
0112 MOVWF INDF
0113 INCF FSR
0114 DECFSZ COUNTER
0115 GOTO 110
0116 INCF OFFSET
0117 INCF CHRIX
0118 GOTO 0
DONE : 0000
INCR : 0065
MAX : 0005
START : 0066
WEER : 006e
run...
RAM after run:
48 : 0030
49 : 002f
50 : 002e
51 : 002d
52 : 002c
53 : 002b
54 : 002a
55 : 0029
56 : 0028
57 : 0027
58 : 0026
59 : 0025
60 : 0024
61 : 0023
62 : 0022
63 : 0021
CHRIX : 0021
COUNTER : 0000
FSR : 0040
OFFSET : 0001
(code) 1 %
<>Enter Category Here