1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
<h3 class="section">Disassembled Byte-Code</h3> <p>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. </p> <p>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. </p> <p>In addition to the stack, byte-code functions can use, bind, and set ordinary Lisp variables, by transferring values between variables and the stack. </p> <dl> <dt id="disassemble">Command: <strong>disassemble</strong> <em>object &optional buffer-or-name</em>
</dt> <dd>
<p>This command displays the disassembled code for <var>object</var>. In interactive use, or if <var>buffer-or-name</var> is <code>nil</code> or omitted, the output goes in a buffer named <samp>*Disassemble*</samp>. If <var>buffer-or-name</var> is non-<code>nil</code>, 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. </p> <p>The argument <var>object</var> can be a function name, a lambda expression (see <a href="lambda-expressions">Lambda Expressions</a>), or a byte-code object (see <a href="byte_002dcode-objects">Byte-Code Objects</a>). If it is a lambda expression, <code>disassemble</code> compiles it and disassembles the resulting compiled code. </p>
</dd>
</dl> <p>Here are two examples of using the <code>disassemble</code> 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 <code>disassemble</code>. </p> <div class="example"> <pre class="example">(defun factorial (integer)
"Compute factorial of an integer."
(if (= 1 integer) 1
(* integer (factorial (1- integer)))))
⇒ factorial
</pre>
<pre class="example">(factorial 4)
⇒ 24
</pre>
<pre class="example">(disassemble 'factorial)
-| byte-code for factorial:
doc: Compute factorial of an integer.
args: (integer)
</pre>
<pre class="example">0 varref integer ; <span class="roman">Get the value of <code>integer</code> and</span>
; <span class="roman">push it onto the stack.</span>
1 constant 1 ; <span class="roman">Push 1 onto stack.</span>
</pre>
<pre class="example">2 eqlsign ; <span class="roman">Pop top two values off stack, compare</span>
; <span class="roman">them, and push result onto stack.</span>
</pre>
<pre class="example">3 goto-if-nil 1 ; <span class="roman">Pop and test top of stack;</span>
; <span class="roman">if <code>nil</code>, go to 1, else continue.</span>
6 constant 1 ; <span class="roman">Push 1 onto top of stack.</span>
7 return ; <span class="roman">Return the top element of the stack.</span>
</pre>
<pre class="example">8:1 varref integer ; <span class="roman">Push value of <code>integer</code> onto stack.</span>
9 constant factorial ; <span class="roman">Push <code>factorial</code> onto stack.</span>
10 varref integer ; <span class="roman">Push value of <code>integer</code> onto stack.</span>
11 sub1 ; <span class="roman">Pop <code>integer</code>, decrement value,</span>
; <span class="roman">push new value onto stack.</span>
12 call 1 ; <span class="roman">Call function <code>factorial</code> using first</span>
; <span class="roman">(i.e., top) stack element as argument;</span>
; <span class="roman">push returned value onto stack.</span>
</pre>
<pre class="example">13 mult ; <span class="roman">Pop top two values off stack, multiply</span>
; <span class="roman">them, and push result onto stack.</span>
14 return ; <span class="roman">Return the top element of the stack.</span>
</pre>
</div> <p>The <code>silly-loop</code> function is somewhat more complex: </p> <div class="example"> <pre class="example">(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
</pre>
<pre class="example">(disassemble 'silly-loop)
-| byte-code for silly-loop:
doc: Return time before and after N iterations of a loop.
args: (n)
</pre>
<pre class="example">0 constant current-time-string ; <span class="roman">Push <code>current-time-string</code></span>
; <span class="roman">onto top of stack.</span>
</pre>
<pre class="example">1 call 0 ; <span class="roman">Call <code>current-time-string</code> with no</span>
; <span class="roman">argument, push result onto stack.</span>
</pre>
<pre class="example">2 varbind t1 ; <span class="roman">Pop stack and bind <code>t1</code> to popped value.</span>
</pre>
<pre class="example">3:1 varref n ; <span class="roman">Get value of <code>n</code> from the environment</span>
; <span class="roman">and push the value on the stack.</span>
4 sub1 ; <span class="roman">Subtract 1 from top of stack.</span>
</pre>
<pre class="example">5 dup ; <span class="roman">Duplicate top of stack; i.e., copy the top</span>
; <span class="roman">of the stack and push copy onto stack.</span>
6 varset n ; <span class="roman">Pop the top of the stack,</span>
; <span class="roman">and bind <code>n</code> to the value.</span>
;; <span class="roman">(In effect, the sequence <code>dup varset</code> copies the top of the stack</span>
;; <span class="roman">into the value of <code>n</code> without popping it.)</span>
</pre>
<pre class="example">7 constant 0 ; <span class="roman">Push 0 onto stack.</span>
8 gtr ; <span class="roman">Pop top two values off stack,</span>
; <span class="roman">test if <var>n</var> is greater than 0</span>
; <span class="roman">and push result onto stack.</span>
</pre>
<pre class="example">9 goto-if-not-nil 1 ; <span class="roman">Goto 1 if <code>n</code> > 0</span>
; <span class="roman">(this continues the while loop)</span>
; <span class="roman">else continue.</span>
</pre>
<pre class="example">12 varref t1 ; <span class="roman">Push value of <code>t1</code> onto stack.</span>
13 constant current-time-string ; <span class="roman">Push <code>current-time-string</code></span>
; <span class="roman">onto the top of the stack.</span>
14 call 0 ; <span class="roman">Call <code>current-time-string</code> again.</span>
</pre>
<pre class="example">15 unbind 1 ; <span class="roman">Unbind <code>t1</code> in local environment.</span>
16 list2 ; <span class="roman">Pop top two elements off stack, create a</span>
; <span class="roman">list of them, and push it onto stack.</span>
17 return ; <span class="roman">Return value of the top of stack.</span>
</pre>
</div><div class="_attribution">
<p class="_attribution-p">
Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc. <br>Licensed under the GNU GPL license.<br>
<a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Disassembly.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Disassembly.html</a>
</p>
</div>
|