summaryrefslogtreecommitdiff
path: root/devdocs/elisp/disassembly.html
blob: d25b993e859b5cd7f84576da1ac711400cdc40ef (plain)
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 &amp;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 (&gt; (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> &gt; 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 &copy; 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>