Miden Assembly (MASM)
Miden assembly is a low-level language for Miden VM, a stack-based zero-knowledge virtual machine.
Key Concepts
Stack Machine
- Operand stack holds field elements (prime field p = 2^64 - 2^32 + 1)
- Top 16 elements directly accessible
- A word = 4 field elements
- Stack grows upward;
pushadds to top, operations consume from top
Stack Notation
[a, b, ...]meansais on top,bbelow- Operations consume inputs and push outputs
- Example:
addwith[3, 5, ...]produces[8, ...]
Quick Reference
Basic Operations
# Arithmetic (field elements)
push.5 push.3 add # [8, ...]
push.10 push.2 sub # [8, ...]
push.4 push.3 mul # [12, ...]
# Stack manipulation
dup.0 # Duplicate top
swap # Swap top two
drop # Remove top
movup.2 # Move 3rd item to top
# Memory
push.42 mem_store.100 # mem[100] = 42
push.100 mem_load # push mem[100]
# Control flow
push.1
if.true
push.10
else
push.20
end
push.5
dup.0 neq.0
while.true
push.1 sub
dup.0 neq.0
end
drop
Program Structure
# Import from core library
use miden::core::math::u64
# Constants
const ADDR = 100
const LIMIT = 1000
# Private procedure with locals
@locals(4)
proc helper
loc_store.0 # Store to local
loc_load.0 # Load from local
end
# Public procedure (exported)
pub proc api_function
exec.helper
end
# Program entry point
begin
push.42
exec.api_function
end
Reference Files
Load these as needed for detailed information:
- instruction_reference.md: Complete instruction set with stack effects and cycle counts
- code_organization.md: Procedures, modules, constants, types, execution contexts
- core_library.md: Standard library modules (u64, hashes, memory, etc.)
Common Patterns
U32 Operations
# u32 values must be < 2^32
push.100 push.50 u32wrapping_add # 150
push.100 push.50 u32lt # 0 (100 < 50 is false)
push.0xFF push.0x0F u32and # 0x0F
U64 Operations (via core library)
use miden::core::math::u64
# u64 = [hi, lo] on stack, with lo deeper (push lo first, then hi)
push.100.0 push.50.0 # Two u64s: 100, 50
exec.u64::wrapping_add # Result: [0, 150]
Conditional Selection
# cdrop: select based on condition
push.10 push.20 push.1 cdrop # [20, ...] (cond=1 selects b)
push.10 push.20 push.0 cdrop # [10, ...] (cond=0 selects a)
Loop with Counter
# repeat.N - compile-time unrolled
repeat.5
push.1 add
end
# while.true - runtime condition
push.1
while.true
# loop body
# must push 0 or 1 for next iteration check
push.0 # exit after one iteration
end
Memory Words
# Store/load 4 elements as word
padw # [0, 0, 0, 0, ...]
push.1.2.3.4 # [4, 3, 2, 1, 0, 0, 0, 0, ...]
push.100 mem_storew_be # Store word at addr 100
dropw padw # Clear and prepare
push.100 mem_loadw_be # Load word from addr 100
Procedure Locals
@locals(8)
proc with_locals
push.42 loc_store.0 # Store to local[0]
loc_load.0 # Load from local[0]
# Word loads (loc_loadw_*) require indices divisible by 4
padw loc_storew_be.4 # Store word at local[4..7]
end
Hashing
# Single word hash
push.1.2.3.4 hash # [digest_word, ...]
# Merge two words
push.1.2.3.4 push.5.6.7.8 hmerge # [digest_word, ...]
Debugging
# Only active in debug mode
debug.stack # Print entire stack
debug.stack.8 # Print top 8 items
debug.mem.100 # Print memory at address 100
debug.local # Print procedure locals
# Tracing (requires -t flag)
trace.1 # Emit trace event
Best Practices
- Validate inputs: Use
u32assert,assertbefore operations with preconditions - Track stack state: Comment stack layout at key points
- Minimize cycles: Check cycle counts for hot paths
- Use locals sparingly: They have overhead vs. stack manipulation
- Word-align memory: Load/store words at addresses divisible by 4
- Return correctly:
call/dyncall/syscallrequire stack depth = 16 on return
Error Patterns
# Division by zero
push.10 push.0 div # FAILS
# Boolean required
push.2
if.true # FAILS: 2 is not boolean
end
# u32 range check
push.0x100000000 u32assert # FAILS: value >= 2^32
