Labels
Manually counting out jump destination addresses would be a monumentally pointless task, so the assembler supports assigning names (or labels) to specific locations in code:
#![allow(unused)] fn main() { extern crate etk_asm; let src = r#" label0: # <- This is a label called "label0", # and it has the value 0, since it is # before any instructions in scope. jumpdest push1 label0 # <- Here we push the value of "label0", # which is zero, onto the stack. jump # Now we jump to zero, which is a # `jumpdest` instruction, looping forever. "#; let mut ingest = etk_asm::ingest::Ingest::new(Vec::new()); ingest.ingest(file!(), src).unwrap(); }
Uses
The obvious (and only, currently) place to use a label is in a push instruction. That said, there are a couple interesting ways to use labels that might not be immediately obvious.
Jump Address
You can push a label, then jump to it like in the above example.
Length
That's not all! You can also use labels to calculate lengths:
#![allow(unused)] fn main() { extern crate etk_asm; let src = r#" push1 start push1 end sub # <- Will leave a 3 on the stack. stop start: pc pc pc end: "#; let mut ingest = etk_asm::ingest::Ingest::new(Vec::new()); ingest.ingest(file!(), src).unwrap(); }
Calculating the length of a blob of instructions is very useful in contract initialization code (also known as constructors).