GNU Emacs 32.0.50 (9008bf64c3) のマニュアルを PLaMo 翻訳で機械翻訳したものです。誤訳を含むことがあります。原文: https://www.gnu.org/software/emacs/manual/html_node/elisp/Disassembly.html ・ emacs-doc.conao3.com

17.7 逆アセンブル済みバイトコード

バイトコードを記述することはなく、その作業はバイトコンパイラに任せられています。しかし、猫のような好奇心を満たすために、逆アセンブラを用意しています。この逆アセンブラは、バイトコンパイルされたコードを人間が読める形式に変換します。

バイトコードインタプリタは、シンプルなスタックマシンとして実装されています。独自のスタックに値をプッシュし、それらをポップして計算に使用し、その計算結果を再びスタックにプッシュします。バイトコード関数が戻る際は、スタックから値をポップし、それを関数の戻り値として返します。

スタックに加えて、バイトコード関数は、変数とスタックの間で値をやり取りすることで、通常のLisp変数の使用、バインド、および設定を行うことができます。

コマンド: disassemble object &optional buffer-or-name

このコマンドは、object の逆アセンブルコードを表示します。対話モードでの使用時、または buffer-or-name が nil であるか省略されている場合、出力は *Disassemble* という名前のバッファに格納されます。buffer-or-name が nil 以外の場合、それはバッファであるか、既存のバッファ名である必要があります。その場合、出力はそこに格納され、point は出力前の位置に残されます。

引数 object には、関数名、ラムダ式(ラムダ式 を参照)、またはバイトコードオブジェクト(クロージャ関数オブジェクト を参照)を指定できます。ラムダ式の場合、disassemble はそれをコンパイルし、生成されたコンパイル済みコードを逆アセンブルします。

disassemble 関数の使用例を2つ挙げます。バイトコードとLispソースを関連付けやすくするため、解説コメントを付け加えました。これらは 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: (arg1)

0   dup                   ; 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 dup                   ; Push value of integer onto stack.
9   constant factorial    ; Push factorial onto stack.
10  stack-ref 2           ; 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.

silly-loop 関数はやや複雑です:

(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: (arg1)

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 as t1.
2:1 stack-ref 1           ; Get value of the argument n
                          ;   and push the value on the stack.
3   sub1                  ; Subtract 1 from top of stack.
4   dup                   ; Duplicate top of stack; i.e., copy the top
                          ;   of the stack and push copy onto stack.
5   stack-set 3           ; Pop the top of the stack,
                          ;   and set n to the value.

;; (In effect, the sequence dup stack-set 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  dup                   ; 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  list2                 ; Pop top two elements off stack, create a
                          ;   list of them, and push it onto stack.
16  return                ; Return value of the top of stack.