Spec-Zone.ru › Elisp

Дизассемблированный байт-код

Люди не пишут байт-код; эту работу выполняет байт-компилятор. Но мы предоставляем дизассемблер, чтобы удовлетворить любопытство, свойственное кошкам. Дизассемблер преобразует скомпилированный в байт-код код в форму, удобную для чтения человеком.

Интерпретатор байт-кода реализован как простая стековая машина. Она помещает значения в собственный стек, а затем извлекает их, чтобы использовать в вычислениях, результаты которых также помещаются в стек. Когда функция байт-кода возвращает значение, она извлекает его из стека и возвращает как результат функции.

Помимо стека, функции байт-кода могут использовать, связывать и присваивать обычные переменные 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 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.

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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API