(lispref.info)Disassembly


Prev: Byte-Code Objects Up: Byte Compilation

Disassembled Byte-Code
======================

   People do not write byte-code; that job is left to the byte compiler.
But we provide a disassembler to satisfy a cat-like curiosity.  The
disassembler converts the byte-compiled code into humanly readable form.

   The byte-code interpreter is implemented as a simple stack machine.
Values get stored by being pushed onto the stack, and are popped off and
manipulated, the results being pushed back onto the stack.  When a
function returns, the top of the stack is popped and returned as the
value of the function.

   In addition to the stack, values used during byte-code execution can
be stored in ordinary Lisp variables.  Variable values can be pushed
onto the stack, and variables can be set by popping the stack.

 - Command: disassemble OBJECT &optional STREAM
     This function prints the disassembled code for OBJECT.  If STREAM
     is supplied, then output goes there.  Otherwise, the disassembled
     code is printed to the stream `standard-output'.  The argument
     OBJECT can be a function name or a lambda expression.

     As a special exception, if this function is used interactively, it
     outputs to a buffer named `*Disassemble*'.

   Here are two examples of using the `disassemble' function.  We have
added explanatory comments to help you relate the byte-code to the Lisp
source; these do not appear in the output of `disassemble'.  These
examples show unoptimized byte-code.  Nowadays byte-code is usually
optimized, but we did not want to rewrite these examples, since they
still serve their purpose.

     (defun factorial (integer)
       "Compute factorial of an integer."
       (if (= 1 integer) 1
         (* integer (factorial (1- integer)))))
          => factorial
     
     (factorial 4)
          => 24
     
     (disassemble 'factorial)
          -| byte-code for factorial:
      doc: Compute factorial of an integer.
      args: (integer)
     
     0   constant 1              ; Push 1 onto stack.
     
     1   varref   integer        ; Get value of `integer'
                                 ;   from the environment
                                 ;   and push the value
                                 ;   onto the stack.
     
     2   eqlsign                 ; Pop top two values off stack,
                                 ;   compare them,
                                 ;   and push result onto stack.
     
     3   goto-if-nil 10          ; Pop and test top of stack;
                                 ;   if `nil', go to 10,
                                 ;   else continue.
     
     6   constant 1              ; Push 1 onto top of stack.
     
     7   goto     17             ; Go to 17 (in this case, 1 will be
                                 ;   returned by the function).
     
     10  constant *              ; Push symbol `*' onto stack.
     
     11  varref   integer        ; Push value of `integer' onto stack.
     
     12  constant factorial      ; Push `factorial' onto stack.
     
     13  varref   integer        ; Push value of `integer' onto stack.
     
     14  sub1                    ; Pop `integer', decrement value,
                                 ;   push new value onto stack.
     
                                 ; Stack now contains:
                                 ;   - decremented value of `integer'
                                 ;   - `factorial'
                                 ;   - value of `integer'
                                 ;   - `*'
     
     15  call     1              ; Call function `factorial' using
                                 ;   the first (i.e., the top) element
                                 ;   of the stack as the argument;
                                 ;   push returned value onto stack.
     
                                 ; Stack now contains:
                                 ;   - result of result of recursive
                                 ;        call to `factorial'
                                 ;   - value of `integer'
                                 ;   - `*'
     
     16  call     2              ; Using the first two
                                 ;   (i.e., the top two)
                                 ;   elements of the stack
                                 ;   as arguments,
                                 ;   call the function `*',
                                 ;   pushing the result onto the stack.
     
     17  return                  ; Return the top element
                                 ;   of the stack.
          => nil

   The `silly-loop' function is somewhat more complex:

     (defun silly-loop (n)
       "Return time before and after N iterations of a loop."
       (let ((t1 (current-time-string)))
         (while (> (setq n (1- n))
                   0))
         (list t1 (current-time-string))))
          => silly-loop
     
     (disassemble 'silly-loop)
          -| byte-code for silly-loop:
      doc: Return time before and after N iterations of a loop.
      args: (n)
     
     0   constant current-time-string  ; Push
                                       ;   `current-time-string'
                                       ;   onto top of stack.
     
     1   call     0              ; Call `current-time-string'
                                 ;    with no argument,
                                 ;    pushing result onto stack.
     
     2   varbind  t1             ; Pop stack and bind `t1'
                                 ;   to popped value.
     
     3   varref   n              ; Get value of `n' from
                                 ;   the environment and push
                                 ;   the value onto the stack.
     
     4   sub1                    ; Subtract 1 from top of stack.
     
     5   dup                     ; Duplicate the top of the stack;
                                 ;   i.e. copy the top of
                                 ;   the stack and push the
                                 ;   copy onto the stack.
     
     6   varset   n              ; Pop the top of the stack,
                                 ;   and bind `n' to the value.
     
                                 ; In effect, the sequence `dup varset'
                                 ;   copies the top of the stack
                                 ;   into the value of `n'
                                 ;   without popping it.
     
     7   constant 0              ; Push 0 onto stack.
     
     8   gtr                     ; Pop top two values off stack,
                                 ;   test if N is greater than 0
                                 ;   and push result onto stack.
     
     9   goto-if-nil-else-pop 17 ; Goto 17 if `n' > 0
                                 ;   else pop top of stack
                                 ;   and continue
                                 ;   (this exits the while loop).
     
     12  constant nil            ; Push `nil' onto stack
                                 ;   (this is the body of the loop).
     
     13  discard                 ; Discard result of the body
                                 ;   of the loop (a while loop
                                 ;   is always evaluated for
                                 ;   its side effects).
     
     14  goto     3              ; Jump back to beginning
                                 ;   of while loop.
     
     17  discard                 ; Discard result of while loop
                                 ;   by popping top of stack.
     
     18  varref   t1             ; Push value of `t1' onto stack.
     
     19  constant current-time-string  ; Push
                                       ;   `current-time-string'
                                       ;   onto top of stack.
     
     20  call     0              ; Call `current-time-string' again.
     
     21  list2                   ; Pop top two elements off stack,
                                 ;   create a list of them,
                                 ;   and push list onto stack.
     
     22  unbind   1              ; Unbind `t1' in local environment.
     
     23  return                  ; Return value of the top of stack.
     
          => nil


automatically generated by info2www