Copyright (C) 2000-2012 |
GNU Info (elisp)DisassemblyDisassembled 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. 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 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 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 ; (this exits the while loop). ; else pop top of stack ; and continue 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. ; This result is the value `nil' that ; was not popped by the goto at 9. 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 version 1.2.2.9 |