(
 ;; main
 (
  (ebp <- esp)
  ;; ebp store stack frame(base)
  ;; make store and restore esp just make it safer
  (esp += -12)
  ;; esp stack pointer
  ;; stack grows downward, towards lower address
  ;; after esp is moved, this position is in use
  
  ;; push args onto the stack, will be the return values
  ((mem esp 0) <- 3) ;; 3rd arg 1
  ((mem esp 4) <- 5) ;; 2nd arg 2
  ((mem esp 8) <- 7) ;; 1st arg 3
  
  ;; print
  (ebx <- (mem esp 0))
  (eax <- (print ebx))
  (ebx <- (mem esp 4))
  (eax <- (print ebx))
  (ebx <- (mem esp 8))
  (eax <- (print ebx))
  
  ;; these 3 args could be used directly in the callee
  ;; but still manipulate the actual values in the stack
  (eax <- esp)
  (edx <- esp)
  (edx += 4)
  (ecx <- esp)
  (ecx += 8)
  
  (call :myfunc)
  
  ;; print again
  (ebx <- (mem esp 0))
  (eax <- (print ebx))
  (ebx <- (mem esp 4))
  (eax <- (print ebx))
  (ebx <- (mem esp 8))
  (eax <- (print ebx))
  
  (esp <- ebp)
  )
 ;; subroutine
 (
  :myfunc
  (ebp <- esp) ;; save esp
  (esp -= 8)
  ;; register esi, edi are callee(function) save
  ((mem esp 0) <- esi)
  ((mem esp 4) <- edi)
  
  (ebx <- (mem eax 0))
  (esi <- (mem edx 0))
  (edi <- (mem ecx 0))
  ((mem ecx 0) <- esi)
  ((mem edx 0) <- edi) ;; swap
  (esi <- ebx)
  (esi -= 1)
  (esi *= 2)
  (ebx -= esi) ;; negate
  ((mem eax 0) <- ebx)
  
  (esi <- (mem esp 0))
  (edi <- (mem esp 4))
  (esp <- ebp) ;; restore esp
  (return)
  )
 
 )
