Дизассемблированный байт-код
Люди не пишут байт-код; эту работу выполняет байт-компилятор. Но мы предоставляем дизассемблер, чтобы удовлетворить любопытство, свойственное кошкам. Дизассемблер преобразует скомпилированный в байт-код код в форму, удобную для чтения человеком.
Интерпретатор байт-кода реализован как простая стековая машина. Она помещает значения в собственный стек, а затем извлекает их, чтобы использовать в вычислениях, результаты которых также помещаются в стек. Когда функция байт-кода возвращает значение, она извлекает его из стека и возвращает как результат функции.
Помимо стека, функции байт-кода могут использовать, связывать и присваивать обычные переменные Lisp, передавая значения между переменными и стеком.
- Команда: disassemble object &optional buffer-or-name
-
Эта команда показывает дизассемблированный код для object. При интерактивном использовании, а также если buffer-or-name равен
nilили не указан, результат выводится в буфер с именем *Disassemble*. Если buffer-or-name не равенnil, он должен быть буфером или именем существующего буфера. В этом случае результат выводится туда, в точку, и точка остаётся перед результатом.Аргумент object может быть именем функции, лямбда-выражением (см. Лямбда-выражения) или объектом байт-кода (см. Объекты функций-замыканий). Если это лямбда-выражение,
disassembleкомпилирует его и дизассемблирует полученный скомпилированный код.
Вот два примера использования функции disassemble. Мы добавили поясняющие комментарии, чтобы помочь соотнести байт-код с исходным кодом 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 ofintegeronto stack. 9 constant factorial ; Pushfactorialonto stack. 10 stack-ref 2 ; Push value ofintegeronto stack. 11 sub1 ; Popinteger, decrement value, ; push new value onto stack. 12 call 1 ; Call functionfactorialusing 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 ; Callcurrent-time-stringwith no ; argument, push result onto stack ast1.
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 setnto the value. ;; (In effect, the sequencedup stack-setcopies the top of ;; the stack into the value ofnwithout 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 oft1onto stack. 13 constant current-time-string ; Pushcurrent-time-string; onto the top of the stack. 14 call 0 ; Callcurrent-time-stringagain.
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.
Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Disassembly.html