Previous: Byte-Code Objects, Up: Byte Compilation [Contents][Index]

### 16.8 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 human-readable form.

The byte-code interpreter is implemented as a simple stack machine. It pushes values onto a stack of its own, then pops them off to use them in calculations whose results are themselves pushed back on the stack. When a byte-code function returns, it pops a value off the stack and returns it as the value of the function.

In addition to the stack, byte-code functions can use, bind, and set ordinary Lisp variables, by transferring values between variables and the stack.

Command: disassemble object &optional buffer-or-name

  This command displays the disassembled code for object. In interactive use, or if buffer-or-name is `nil` or omitted, the output goes in a buffer named `*Disassemble*`. If buffer-or-name is non-`nil`, it must be a buffer or the name of an existing buffer. Then the output goes there, at point, and point is left before the output.

  The argument object can be a function name, a lambda expression (see Lambda Expressions), or a byte-code object (see Byte-Code Objects). If it is a lambda expression, `disassemble` compiles it and disassembles the resulting compiled code.

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`.

    (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   varref   integer      ; Get the value of integer and
                              ;   push it onto the stack.
    1   constant 1            ; Push 1 onto stack.

    2   eqlsign               ; Pop top two values off stack, compare
                              ;   them, and push result onto stack.

    3   goto-if-nil 1         ; Pop and test top of stack;
                              ;   if nil, go to 1, else continue.
    6   constant 1            ; Push 1 onto top of stack.
    7   return                ; Return the top element of the stack.

    8:1 varref   integer      ; Push value of integer onto stack.
    9   constant factorial    ; Push factorial onto stack.
    10  varref   integer      ; Push value of integer onto stack.
    11  sub1                  ; Pop integer, decrement value,
                              ;   push new value onto stack.
    12  call     1            ; Call function factorial using first
                              ;   (i.e., top) stack element as argument;
                              ;   push returned value onto stack.

    13 mult                   ; Pop top two values off stack, multiply
                              ;   them, and push result onto stack.
    14 return                 ; Return the top element of the stack.

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, push result onto stack.

    2   varbind  t1           ; Pop stack and bind t1 to popped value.

    3:1 varref   n            ; Get value of n from the environment
                              ;   and push the value on the stack.
    4   sub1                  ; Subtract 1 from top of stack.

    5   dup                   ; Duplicate top of stack; i.e., copy the top
                              ;   of the stack and push copy onto 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-not-nil 1     ; Goto 1 if n > 0
                              ;   (this continues the while loop)
                              ;   else continue.

    12  varref   t1           ; Push value of t1 onto stack.
    13  constant current-time-string  ; Push current-time-string
                                      ;   onto the top of the stack.
    14  call     0            ; Call current-time-string again.

    15  unbind   1            ; Unbind t1 in local environment.
    16  list2                 ; Pop top two elements off stack, create a
                              ;   list of them, and push it onto stack.
    17  return                ; Return value of the top of stack.

Previous: Byte-Code Objects, Up: Byte Compilation [Contents][Index]