Basics :
Picshell is composed of two main parts :- The PIC Engine, which is responsible for the PIC simulation
- The User Interface, which allow code editing and user interaction with the engine (debugger).
More details about PicShell's Engine :

This diagram really looks more complex than it is... Most of the complexity (all that Inst, InstModel, Mnemonic ...) are used to gain some performance.
Here are the major actors behind the scene :
- PicEngine, This is the main object to intercat with. it contains methods for execution (runNext(), runTillAdress()...)
- State, this one should more be called "Core" as it's not just a state, this object holds memory (program, eeprom...), and knows what
to do when a register is modified. for now, it's based on a PIC 16F877
- PicBuilder, used internally, this object is an utility object that is responsible for providing
an array of instructions. (only 14 the bit instruction set in supported for now)
- HexReader, This one is responsible for reading an hex file.
- Inst, Basicly, an instruction, with its address, destination, value, bit and model (which is an InstModel, see bellow)
- InstModel, This one mainly map a Mnemonic (NOP, ADDLW...) to a python method (code) used to update the State Object
- Mnemonic, Regroup all python methods used to update the State Object
Using the Pic Engine without UI :
Let's first start by writting a little program with JALv2 :include pjal_877 include pic_general pragma target clock 4_000_000 pragma target fuses 0x3F32 port_B_direction = all_output forever loop PORTB = 1 PORTB = 3 PORTB = 5 PORTB = 7 end loopCompiling this code with JalV2 will produce an hex file... that looks like that :
:020000040000FA :1000000007282108860008008312A1000128A0010A :1000100083168601013004200330042005300420BB :06002000073004200A284D :02400E00323F3F :00000001FFWe can now use the engine to dissamble that hex file, to view the asm instructions.
Here is a small python program that take the hex file, and displays its asm instructions.
Note that the hex may have been produced by another tool than JAL (even if it's still my favorite one !!!).
from picshell.engine.core.PicEngine import PicEngine
from picshell.engine.util.Format import Format
from picshell.engine.core.State import State
print "Start"
engine = PicEngine.newInstance(State(),"D:\\picshell\\examples\\test.hex")
for inst in engine.instructionList[:engine.lastAddress+1]:
Format.dumpInstruction(inst)
print "End"
Which produce the following result :
Start
0 GOTO 7
1 MOVF(w) 33
2 MOVWF(f) 6
3 RETURN
4 BCF 3, 5
5 MOVWF(f) 33
6 GOTO 1
7 CLRF(f) 32
8 BSF 3, 5
9 CLRF(f) 6
10 MOVLW 1
11 CALL 4
12 MOVLW 3
13 CALL 4
14 MOVLW 5
15 CALL 4
16 MOVLW 7
17 CALL 4
18 GOTO 10
End
Let's now execute this code once (the following program will execute the code till it reaches the last address
and then the program will break. To dispay the result, we use an "Engine Monitor" which is called by the engine
before and after each instruction's execution. Format.formatInstruction(inst, self.level, False) do some black magic for now
to display the result.
from picshell.engine.core.PicEngine import PicEngine
from picshell.engine.util.Format import Format
from picshell.engine.core.State import State
class EngineMonitor :
def __init__(self):
self.level = 0
def executeBefore (self,engine,inst):
print Format.formatInstruction(inst, self.level, False)
def executeAfter (self,engine,inst):
if inst.model.mnemonic == "CALL" :
self.level += 1
if inst.model.mnemonic == "RETURN" :
self.level -= 1
# Code execution start here
print "Start"
engine = PicEngine.newInstance(State(),"D:\\picshell\\examples\\test.hex")
engine.monitors = [EngineMonitor()]
engine.runTillAddress(engine.lastAddress)
print "End"
Which produce the following result :
Start
0 GOTO 7
7 CLRF(f) 32
8 BSF 3, 5
9 CLRF(f) 6
10 MOVLW 1
11 CALL 4
4 | BCF 3, 5
5 | MOVWF(f) 33
6 | GOTO 1
1 | MOVF(w) 33
2 | MOVWF(f) 6
3 | RETURN
12 MOVLW 3
13 CALL 4
4 | BCF 3, 5
5 | MOVWF(f) 33
6 | GOTO 1
1 | MOVF(w) 33
2 | MOVWF(f) 6
3 | RETURN
14 MOVLW 5
15 CALL 4
4 | BCF 3, 5
5 | MOVWF(f) 33
6 | GOTO 1
1 | MOVF(w) 33
2 | MOVWF(f) 6
3 | RETURN
16 MOVLW 7
17 CALL 4
4 | BCF 3, 5
5 | MOVWF(f) 33
6 | GOTO 1
1 | MOVF(w) 33
2 | MOVWF(f) 6
3 | RETURN
18 GOTO 10
End
Let's now say that we are not intersted in all this details, and that we just want to see what happend on PORTB.
That's pretty easy to do using a "State monitor", like in this example :
from picshell.engine.core.PicEngine import PicEngine
from picshell.engine.core.State import State
class StateMonitor :
def __init__(self):
self.address = 6 # PORTB
def execute(self,value):
print value
# Code execution start here
#
print "Start"
engine = PicEngine.newInstance(State(),"D:\\picshell\\examples\\test.hex")
engine.state.setMonitors([StateMonitor()])
engine.runTillAddress(engine.lastAddress)
print "End"
Which produce the following result :
Start 1 3 5 7 EndOk that's all for now, just send me an email if you are interested or need some more informations.