From 754bbf7a25a8dda49b5d08ef0d0443bbf5af0e36 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sun, 7 Apr 2024 13:41:34 -0500 Subject: new repository --- devdocs/elisp/disassembly.html | 107 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 devdocs/elisp/disassembly.html (limited to 'devdocs/elisp/disassembly.html') diff --git a/devdocs/elisp/disassembly.html b/devdocs/elisp/disassembly.html new file mode 100644 index 00000000..d25b993e --- /dev/null +++ b/devdocs/elisp/disassembly.html @@ -0,0 +1,107 @@ +

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

+ Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
+ https://www.gnu.org/software/emacs/manual/html_node/elisp/Disassembly.html +

+
-- cgit v1.2.3