summaryrefslogtreecommitdiff
path: root/devdocs/elisp/disassembly.html
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2024-04-07 13:41:34 -0500
committerCraig Jennings <c@cjennings.net>2024-04-07 13:41:34 -0500
commit754bbf7a25a8dda49b5d08ef0d0443bbf5af0e36 (patch)
treef1190704f78f04a2b0b4c977d20fe96a828377f1 /devdocs/elisp/disassembly.html
new repository
Diffstat (limited to 'devdocs/elisp/disassembly.html')
-rw-r--r--devdocs/elisp/disassembly.html107
1 files changed, 107 insertions, 0 deletions
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 @@
+ <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>