GNU MIX Development Kit (mdk): Начало работы
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3. Начало работы
В этой главе вы найдёте примеры сеансов кодирования, компиляции, запуска и отладки с использованием утилит MDK. Предполагается знакомство с мифическим компьютером MIX и его языке ассемблера MIXAL (описанными в "Искусстве программирования" Кнута). Чтобы освежить их в памяти, см. 2. Учебник по MIX и MIXAL.
исходных файлов в двоичный формат.
3.1 Написание исходного файла Пример исходного файла на MIXAL. 3.2 Компиляция Использование mixasm
для компиляции
запуска и отладки программ.
3.3 Запуск программы 3.4 Использование mixguile
Использование интерпретатора Scheme для
3.5 Использование Scheme в mixvm
иgmixvm
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3.1 Написание исходного файла
Программы на MIXAL могут быть написаны в виде ASCII-файлов в любом текстовом редакторе. Приведём обязательную программу hello world, написанную на языке ассемблера MIXAL.
* (1) * hello.mixal: сказать 'hello world' на MIXAL (2) * (3) * label ins operand comment (4) TERM EQU 19 номер устройства консоли в MIX (5) ORIG 1000 начальный адрес (6) START OUT MSG(TERM) вывести данные с адреса MSG (7) HLT прекратить работу (8) MSG ALF "MIXAL" (9) ALF " HELL" (10) ALF "O WOR" (11) ALF "LD " (12) END START конец программы (13) |
-
необязательная метка, которая либо ссылается на текущий адрес памяти
(как
START
иMSG
в строках 7 и 9), либо определяет символ (TERM
) (если она присутствует, метка обязана начинаться в первой колонке строки, ибо первый пробельный символ в строке отмечает начало второго поля). -
мнемоника операции, которая может представляет либо инструкцию MIX
(
OUT
иHLT
в строках 7 и 9), либо псевдоинструкцию ассемблера (например, псевдоинструкцияORIG
в строке 6(10)). - необязательный операнд (псевдо)инструкции, и
- необязательный комментарий -- произвольный текст.
Строки 9-12 в файле `hello.mixal' показываеют также второе (и
последнее) различие между определениями MIXAL Кнута и нашими: операнд
псевдоинструкции ALf
(слово из пяти литер) должно быть заключено
в двойные кавычки(11).
Если вы знакомы с MIXAL, работа этого примера программы должна быть
понятна. См. полное определение MIXAL в томе 1 "Искусства программирования",
учебник -- 2. Учебник по MIX и MIXAL.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3.2 Компиляция
В состав MDK входят три эмулятора компьютера MIX: mixvm
,
gmixvm
и mixguile
. Они могут выполнять двоичные файлы,
содержащие инструкции MIX, записанные в двоичном представлении.
Транслировать исходные файлы на MIXAL в такой двоичный вид можно
ассемблером MIXAL mixasm
. Так, для компиляции файла
`hello.mixal' вы можете использовать в командной строке оболочки
следующую команду:
mixasm -g hello RET |
Если исходный файл не содержит ошибок, будет создан двоичный файл
`hello.mix', который может быть загружен и запущен виртуальной
машиной MIX. Флаг -g
указывает ассемблеру включать в
исполняемый файл отладочную информацию (полное описание всех параметров
компиляции см. в 5. mixasm
, ассемблер MIXAL). Теперь всё готово для запуска вашей
первой программы MIX, что описано в следующем разделе.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3.3 Запуск программы
MIX -- мифический компьютер, и бесполезно пытаться заказать его у вашего поставщика аппаратного обеспечения. Тем не менее, MDK предоставляет три программных эмулятора этого компьютера. Это
-
mixvm
, эмулятор, ориентированный на использование командной строки, -
gmixvm
, основанный на GTK графический интерфейсmixvm
, и -
mixguile
, оболочка Guile со встроенным эмулятором MIX.
Все три эмулятора используют один и тот же набор команд пользователя,
но, как отмечено выше, предлагают различные пользовательские интерфейсы.
В этом разделе мы опишем некоторые из этих команд и покажем вам, как
пользоваться ими в командной строке mixvm
. Вы можете также
использовать их в командной строке gmixvm
(see section 7. gmixvm
, виртуальная машина на основе GTK)
или работать со встроенными примитивами Scheme mixguile
(see section 3.4 Использование mixguile
).
Используя эмуляторы MIX вы можете запускать ваши программы на MIXAL,
предварительно скомпилированные mixasm
в двоичные файлы `.mix'.
mixvm
может использоваться в интерактивном или в
неинтерактивном режиме. В втором случае mixvm
загружает
вашу программу в память, выполняет её (создавая выходные файлы,
обусловленые наличием в программе инструкций MIXAL OUT
) и
завершает работу при обнаружении инструкции HLT
. В интерактивном
режиме вы попадёте в приглашение оболочки, позволяющее вам давать
команды работающей виртуальной машине. Эти команды позволят вам
загружать, запускать и отлаживать программы, а также проверять состояние
компьютера MIX (содержимое регистров, ячеек памяти и т.д.).
3.3.1 Неинтерактивный режим 3.3.2 Интерактивный режим 3.3.3 Команды отладки
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3.3.1 Неинтерактивный режим
Для запуска mixvm
в неинтерактивном режиме используйте флаг
-r
. Так, для запуска программы `hello.mix' введите:
mixvm -r hello RET |
в приглашении командной строки. Вы получите такой вывод:
MIXAL HELLO WORLD |
Поскольку наша программа использует для вывода устройство MIX
номер 19 (see section 3.1 Написание исходного файла), вывод направляется
на стандартный вывод оболочки. При использовании любого другого
устройства MIX (диски, барабаны, строчный принтер и т.д.) mixvm
создаст файл, имя которого соответствует устройству (например,
`disk4.dev') и запишет вывод туда(12).
Виртуальная машина может также сообщить время выполнения программы,
в соответствии со временем (виртуальным), требуемым каждой инструкцией
(see section 2.1.2.12 Временные характеристики). Вывод статистики времени выполнения
включается флагом -t
. Запуск
mixvm -t -r hello RET |
даст следующий вывод:
MIXAL HELLO WORLD ** Execution time: 11 |
Иногда вы предпочтёте сохранять результаты работы вашей программы в
регистрах MIX, а не записывать их на устройствах. В таких случаях
будет полезен флаг mixvm
-d
, заставляющий mixvm
после выполнения загруженной программы выводить содержимое регистров
и флагов. Например, введя в приглашении оболочки следующую команду:
mixvm -d -r hello |
вы получите такой вывод:
MIXAL HELLO WORLD rA: + 00 00 00 00 00 (0000000000) rX: + 00 00 00 00 00 (0000000000) rJ: + 00 00 (0000) rI1: + 00 00 (0000) rI2: + 00 00 (0000) rI3: + 00 00 (0000) rI4: + 00 00 (0000) rI5: + 00 00 (0000) rI6: + 00 00 (0000) Overflow: F Cmp: E |
включающий, помимо вывода программы и времени выполнения, содержимое регистров MIX и значения триггера переполнения и флага сравнения (признаться, не слишком интересные в нашем примере).
Как можно видеть, неинтерактивный запуск программ накладывает много ограничений. Вы не можете ни заглянуть в память машины, ни выполнять инструкции программы по шагам или устанавливать точки останова(13). Перейдём к интерактивному режиму.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3.3.2 Интерактивный режим
Чтобы войти в интерактивный режим виртуальной машины MIX, введите:
mixvm RET |
в приглашении командной строки. Вы попадёте в командную оболочку
mixvm
и увидите следующее приглашение:
MIX > |
Виртуальная машина инициализирована и готова к вашим командам. Командная
оболочка mixvm
использует GNU readline, и поэтому в вашем
распоряжении находятся дополнение команд (TAB) и возиожности
истории команд, равно как и другие способы редактирования командных
строк, общие для всех использующих эту библиотеку утилит (полное
описание средств редактирования строк readline см. в @xref{Command Line Editing,,,Readline}.)
Обычно, первое, что вы захотите сделать, это загрузка в память
скомпилированной программы MIX. Это осуществляется командой load
,
принимающей в качестве аргумента название загружаемого файла `.mix'.
Так, ввод
MIX > load hello RET Program loaded. Start address: 3000 MIX > |
загрузит `hello.mix' в память виртуальной машины и установит
счётчик программы на адрес первой инструкции. Вы можете посмотреть
содержимое счётчика программы командой pc
:
MIX > pc Current address: 3000 MIX > |
После загрузки всё готово к запуску программы. Для этого, как вы, конечно,
догадались, служит команда run
:
MIX > run Running ... MIXAL HELLO WORLD ... done Elapsed time: 11 /Total program time: 11 (Total uptime: 11) MIX > |
Обратите внимание, что статистика времена более полна. Вы видите
прошедшее время выполнения (т.е. время выполнения инструкций после
последней точки останова), общее время выполнения программы до данного
момента (которое в нашем случае совпадает с прошедшим временем, поскольку
нет точек останова), и общее время работы виртуальной машины (вы можете
загружать и запускать несколько программ в одном сеансе)(14). После выполнения программы счётчик
программы будет указывать на адрес слова, следующего за инструкцией
HLT
. В нашем случае запрос значения счётчика программы после
завершения работы программы даст:
MIX > pc Current address: 3002 MIX > |
Вы можете просмотреть содержимое ячейки памяти, передавая её адрес
в качестве аргумента команды pmem
:
MIX > pmem 3001 3001: + 00 00 00 02 05 (0000000133) MIX > |
и убедиться в том, что ячейка 3001 содержит двоичное представление
инструкции HLT
. Также аргументом pmem
может быть
диапазон адресов в виде ОТ-ДО:
MIX > pmem 3000-3006 3000: + 46 58 00 19 37 (0786957541) 3001: + 00 00 00 02 05 (0000000133) 3002: + 14 09 27 01 13 (0237350989) 3003: + 00 08 05 13 13 (0002118477) 3004: + 16 00 26 16 19 (0268542995) 3005: + 13 04 00 00 00 (0219152384) 3006: + 00 00 00 00 00 (0000000000) MIX > |
Аналогичным образом вы можете просматривать содержимое регистров и флагов MIX. Например, чтобы запросить содержимое регистра A вы можете ввести:
MIX > preg A rA: + 00 00 00 00 00 (0000000000) MIX > |
Используйте команду help
, чтобы получить список всех доступных
команд и help КОМАНДА
чтобы получить справку по конкретной
команде, например:
MIX > help run run Run loaded or given MIX code file. Usage: run [FILENAME] MIX > |
Полный список доступных в приглашении MIX команд см. в 6. mixvm
, эмулятор компьютера MIX. В
следующем подразделе вы найдёте краткое описание команд, полезных
для отладки программ.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3.3.3 Команды отладки
Интерактивный режим mixvm
даёт возможности пошагового выполнения
программ и установки точек останова. Для пошагового выполнения используйте
next
. Чтобы выполнить наш пример из двух инструкций `hello.mix',
вы можете сделать следующее:
MIX > load hello Program loaded. Start address: 3000 MIX > pc Current address: 3000 MIX > next MIXAL HELLO WORLD Elapsed time: 1 /Total program time: 1 (Total uptime: 1) MIX > pc Current address: 3001 MIX > next End of program reached at address 3002 Elapsed time: 10 /Total program time: 11 (Total uptime: 11) MIX > pc Current address: 3002 MIX > next MIXAL HELLO WORLD Elapsed time: 1 /Total program time: 1 (Total uptime: 12) MIX > MIX > run Running ... ... done Elapsed time: 10 /Total program time: 11 (Total uptime: 22) MIX > |
Установить по заданному адресу точку останова можно командой sbpa
(set breakpoint at address, установить точку останова по адресу). Если
установлена точка останова, run
остановится перед выполнением
инструкции по заданному адресу. Новое выполнение run
завершит
выполнение программы. Вернёмся к нашему примеру hello world:
MIX > sbpa 3001 Breakpoint set at address 3001 MIX > run Running ... MIXAL HELLO WORLD ... stopped: breakpoint at line 8 (address 3001) Elapsed time: 1 /Total program time: 1 (Total uptime: 23) MIX > run Running ... ... done Elapsed time: 10 /Total program time: 11 (Total uptime: 33) MIX > |
Заметьте, что поскольку мы компилировали `hello.mixal' с отладочной
информацией (флаг -g
mixasm
), виртуальноая машина может
указать нам строку исходного файла, соответствующую точке останова.
Собственно говоря, можно непосредственно устанавливать точки останова
на строках исходного кода командой sbp НОМЕР_СТРОКИ
:
MIX > sbp 4 Breakpoint set at line 7 MIX > |
sbp
устанавливает точку останова на первой осмысленной строке
исходного кода. Так, в вышеприведённом примере мы потребовали установить
точку останова на строке, не соответствующей инструкции MIX, и она была
установлена на первой строке, содержащей реальную инструкции после
заданной. Чтобы снять точку останова, используйте cbpa АДРЕС
и cbp НОМЕР_СТРОКИ
, или cabp
чтобы удалить все установленные
точки останова. Вы можете также установить условную точку останова, т.е.
указать mixvm
прерывать выполнение программы только когда
меняется значение регистра, ячейки памяти, флага сравнения или триггера
переполнения командами sbp[rmco]
(see section 6.2.2 Команды отладки).
MIXAL позволяет определять символические константы, либо используя
псевдоинструкцию EQU
, либо начиная строку инструкции с метки
(что присваивает метке значение текущего адреса памяти). Поэтому с
каждой программой на MIXAL связана таблица символов, которую вы можете
просматривать командой psym
. В нашем примере hello world вы
можете получить следующий вывод:
MIX > psym START: 3000 TERM: 19 MSG: 3002 MIX > |
Также при отладке полезны команды strace
(включающая отслеживание
выполненных инструкций), pbt
(выводящая след выполненных инструкций)
и weval
(вычисляющая на лету значение w-выражения). Полное описание
всех доступных команд MIX см. в 6. mixvm
, эмулятор компьютера MIX.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3.4 Использование mixguile
Используя mixguile
вы можете запускать эмулятор MIX, встроенный в
оболочку Guile, т.е. использовать функции и программы Scheme. Как и
mixvm
, mixguile
может работать как в интерактивном, так и
в неинтерактивном режиме. Следующие подразделы содержат краткое описание
использование этого эмулятора MIX.
3.4.1 Оболочка mixguile
Использование виртуальной машины MIX Scheme. 3.4.2 Дополнительные функции MIX Scheme Функции Scheme, доступные виртуальной машине. 3.4.3 Определение новых функций Определение собственных функции Scheme. 3.4.4 Функции-ловушки 3.4.5 Скрипты Scheme
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3.4.1 Оболочка mixguile
Если вы введёте
mixguile RET |
guile> |
mixvm
, описанная в предыдущих разделах (и в see section 6. mixvm
, эмулятор компьютера MIX) имеет
соответствующую функцию Scheme, название которой образовано добавлением
к названию команды префикса mix-
. Так, чтобы загрузить программу
hello world, можно ввести:
guile> (mix-load "hello") Program loaded. Start address: 3000 guile> |
mix-run
:
guile> (mix-run) Running ... MIXAL HELLO WORLD ... done Elapsed time: 11 /Total program time: 11 (Total uptime: 11) guile> |
mix-next
, или установить точку останова:
guile> (mix-sbp 4) Breakpoint set at line 5 guile> |
guile> (mix-preg 'A) rA: + 00 00 00 00 00 (0000000000) guile> |
Основная идея: в вашем распоряжении находятся все команды mixvm
и gmixvm
в виде функций mix-
. Но, если вас это удивляет,
заметим, что это только начало. В вашем распоряжении также полный
интерпретатор Scheme, и вы можете, например, определять новые функции,
комбинируя функции mix-
и остальные примитивы Scheme. В следующих
разделах вы обнаружите примеры использование интерпретатора Guile.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3.4.2 Дополнительные функции MIX Scheme
Функции mix-
, соответствующие командам mixvm
, не возвращают
никакого значения и работают только засчёт побочных эффектов (возможно,
включающих информационные сообщения на стандартный вывод и/или поток
ошибок). При написании собственных функций Scheme для управления виртуальной
машиной MIX из mixguile
(see section 3.4.3 Определение новых функций), вам,
вероятно, понадобятся функции Scheme, возвращающие значение регистров,
ячеек памяти и т.д. Не волнуйтесь, mixguile
предлагает вам и такие
функции. Например, чтобы получить значение (числовое) регистра, можно
использовать mix-reg
:
guile> (mix-reg 'I2) 0 guile> |
(mix-preg 'I2)
, выражение (mix-reg
'I2)
в этом примере вычисляет номер Scheme и не создаёт никакого
побочного эффекта:
guile> (number? (mix-reg 'I2)) #t guile> (number? (mix-preg 'I2)) rI2: + 00 00 (0000) #f guile> |
Аналогичным образом можно обращаться к содержимому памяти командой
(mix-cell)
, или к счётчику программы командой (mix-loc)
:
guile> (mix-cell 3000) 786957541 guile> (mix-loc) 3002 guile> |
Значение флага сравнения и триггера переполнения возвращают функции
mix-cmp
и mix-over
соответственно. Полный список
дополнительных функций см. в 8. mixguile
, виртуальная машина на основе Scheme.
В следующем разделе мы увидим пример использования этих функций для
расширения функциональности mixguile
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3.4.3 Определение новых функций
Scheme -- мощный язык, и вы можете использовать его внутри mixguile
,
чтобы легко расширять возможности интерпретатора MIX. Например, вы легко
можете определить функцию, загружающую файл, выводяющую его имя,
выполняющую его и, наконец, показывающую содержимое регистров, всё в один
приём:
guile> (define my-load-and-run RET (lambda (file) RET (mix-load file) RET (display "File loaded: ") RET (mix-pprog) RET (mix-run) RET (mix-preg))) RET guile> |
guile> (my-load-and-run "hello") Program loaded. Start address: 3000 File loaded: hello.mix Running ... MIXAL HELLO WORLD ... done Elapsed time: 11 /Total program time: 11 (Total uptime: 33) rA: + 00 00 00 00 00 (0000000000) rX: + 00 00 00 00 00 (0000000000) rJ: + 00 00 (0000) rI1: + 00 00 (0000) rI2: + 00 00 (0000) rI3: + 00 00 (0000) rI4: + 00 00 (0000) rI5: + 00 00 (0000) rI6: + 00 00 (0000) guile> |
Или, быть может, вы хотите иметь функцию, перед выполнением программы устанавливающую точку останова на указанной строке:
guile> (define my-load-and-run-with-bp (lambda (file line) (mix-load file) (mix-sbp line) (mix-run))) guile> (my-load-and-run-with-bp "samples/primes" 10) Program loaded. Start address: 3000 Breakpoint set at line 10 Running ... ... stopped: breakpoint at line 10 (address 3001) Elapsed time: 1 /Total program time: 1 (Total uptime: 45) guile> |
Третьим примером рассмотрим функцию, загружающую программу, выполняющую её и выводящую содержимое памяти между начальным и конечным адресами программы:
guile> (define my-run (lambda (file) (mix-load file) (let ((start (mix-loc))) (mix-run) (mix-pmem start (mix-loc))))) guile> (my-run "hello") Program loaded. Start address: 3000 Running ... MIXAL HELLO WORLD ... done Elapsed time: 11 /Total program time: 11 (Total uptime: 11) 3000: + 46 58 00 19 37 (0786957541) 3001: + 00 00 00 02 05 (0000000133) 3002: + 14 09 27 01 13 (0237350989) guile> |
Как вы видите, возможности практически не ограничены. Конечно, вводить
определение функций при каждом запуске mixguile
не нужно. Вы можете
записать их в файл и загрузить функцией Scheme load
. Например,
вы можете создать файл, скажем, `functions.scm' с вашими определениями
(или любыми выражениями Scheme) и загрузить его в приглашении mixguile
:
guile> (load "functions.scm") |
Кроме того, вы можете указать mixguile
загружать его каждый раз.
При запуске mixguile
, она проверяет файл `mixguile.scm' в
каталоге конфигурации MDK (`~/.mdk') и, если он существует,
загружает его перед тем, как войти в REPL. Поэтому вы можете скопировать
ваши определения в этот файла или загрузить `functions.scm' из
`mixguile.scm'.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3.4.4 Функции-ловушки
Ловушки -- это функции, вызываемые до или после некоторого события.
В mixguile
вы можете определять ловушки команд и остановов,
связанные, соответственно, с выполнением команды и с прерыванием
программы. Следующие разделы содержат учебник по использованию
функций-ловушек в mixguile
.
3.4.4.1 Ловушки команд 3.4.4.2 Ловушки остановов
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3.4.4.1 Ловушки команд
В предыдущем разделе мы видели как с помощью определённых пользователем
функций расширяется функциональномть mixguile
. Часто вы будете
писать новые функции, некоторым образом усовершенствующие работу
встроенных команд mixvm
, по следующему образцу:
- Подготовиться к выполнению команды
- Выполнить желаемую команду
- Осуществить операции после выполнения команды
Мы называем функции, выполняемые на шаге (a) ловушками до команды,
а на шаге (c) -- ловушками после команды. mixguile
позволяет
задать ловушки до и после любой команды mixvm
, используя функции
mix-add-pre-hook
и mix-add-post-hook
, принимающие в
качестве аргументов символ, называющий команду, и выполняемую перед
командой (после команды) функцию. Другими словами, mixguile
будет выполнять шаги (a) и (c) при каждом выполнении (b). Функции-ловушки
должны принимать единственный аргумент, являющийся списком строк
аргументов команды. Например, определим следующие ловушки для команды
next
:
(define next-pre-hook (lambda (arglist) (mix-slog #f))) (define next-post-hook (lambda (arglist) (display "Stopped at line ") (display (mix-src-line-no)) (display ": ") (display (mix-src-line)) (newline) (mix-slog #t))) |
mix-slog
для отключения
информационных сообщений, создаваемых виртуальной машиной, поскольку
генерируем свои сообщения в ловушке после команды. Для установки
этих ловушек нам следует написать:
(mix-add-pre-hook 'next next-pre-hook) (mix-add-post-hook 'next next-post-hook) |
mixguile
.
При выполнении mix-next
мы получим следующий результат:
guile> (mix-next) MIXAL HELLO WORLD Stopped at line 6: HLT guile> |
Во втором, более сложном, примере, определим ловушки, выводящие адрес
и содержимое ячейки памяти, модифицированной smem
. Функции-ловушки
должны быть примерно такими:
(define smem-pre-hook (lambda (arglist) (if (eq? (length arglist) 2) (begin (display "Changing address ") (display (car arglist)) (newline) (display "Old contents: ") (display (mix-cell (string->number (car arglist)))) (newline)) (error "Wrong arguments" arglist)))) (define smem-post-hook (lambda (arglist) (if (eq? (length arglist) 2) (begin (display "New contents: ") (display (mix-cell (string->number (car arglist)))) (newline))))) |
(mix-add-pre-hook 'smem smem-pre-hook) (mix-add-post-hook 'smem smem-post-hook) |
mix-smem
даст:
guile> (mix-smem 2000 100) Changing address 2000 Old contents: 0 New contents: 100 guile> |
Вы можете добавить заданной команде любое количество ловушек. Они будут
выполняться в том порядке, в котором они зарегистрированы. Вы можете
также определить глобальные ловушки до (после) команды, которые будут
выполняться перед (после) любой выполняемой команды mixvm
.
Глобальные функции-ловушки должны принимать два аргумента, а именно
строку, называющую вызываемую команду, и список строк её аргументов.
Устанавливаются они функциями Scheme mix-add-global-pre-hook
и
mix-add-global-post-hook
. Простой пример глобальной ловушки:
guile> (define pre-hook (lambda (cmd args) (display cmd) (display " invoked with arguments ") (display args) (newline))) guile> (mix-add-global-pre-hook pre-hook) ok guile> (mix-pmem 120 125) pmem invoked with arguments (120-125) 0120: + 00 00 00 00 00 (0000000000) 0121: + 00 00 00 00 00 (0000000000) 0122: + 00 00 00 00 00 (0000000000) 0123: + 00 00 00 00 00 (0000000000) 0124: + 00 00 00 00 00 (0000000000) 0125: + 00 00 00 00 00 (0000000000) guile> |
Заметьте, что если внутри глобальной ловушки вы вызываете команды
mixvm
, будут выполняться и их ловушки команд. Так, если вы
установили описанные выше ловушки next
и глобальные ловушки,
выполнение mix-next
приведёт к следующему результату:
guile> (mix-next 5) next invoked with arguments (5) slog invoked with arguments (off) MIXAL HELLO WORLD Stopped at line 7: MSG ALF "MIXAL" slog invoked with arguments (on) guile> |
Рисковые читатели могут рассматривать вышеприведённые глобальные ловушки как прообраз утилиты, ведущей лог команд или как макрос, записывающий все ваши команды, чтобы дать возможность повторения.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3.4.4.2 Ловушки остановов
В предыдущем разделе мы рассмотрели, как связывать ловушки с выполнением команд, но это ещё не всё. Вы можете также связывать функции-ловушки с прерыванием выполнения программы, т.е. задавать функции, вызываемые при каждой остановке выполнения программы MIX из-за точки останова, обязательной или условной. Ловушки останова принимают в качестве аргументов номер строки и адреса памяти, где произошёл останов. Простая ловушка, ведущая лог строк и адресов остановов, может быть определена:
(define break-hook (lambda (line address) (display "Breakpoint encountered at line ") (display line) (display " and address ") (display address) (newline))) |
(mix-add-break-hook break-hook) (mix-add-cond-break-hook break-hook) |
break-code
(15).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3.4.5 Скрипты Scheme
Другой полезный способ использования mixguile
-- написание
исполняемых скриптов, предоставляющих набор команд. Это делается
флагом -s
mixguile
(будучи оболочкой Scheme, mixguile
принимает все параметры команды guile
, для получения списка всех
доступных параметров команды введите mixguile -h
). Например,
если у вас есть очень полезная программа MIX `foo.mix', которую
вы собираетесь использовать достаточно часто, вам не нужно каждый раз
запускать виртуальную машину MIX, загружать и выполнять программу,
можно просто написать скрипт Scheme:
#! /usr/bin/mixguile -s !# ;;; runprimes: выполняет программу primes.mix ;; загрузить файл, который вы хотите запустить (mix-load "../samples/primes") ;; выполнить его (mix-run) ;; вывести содержимое регистров (mix-pall) ;; ... |
Просто сохраните это скрипт в файле, скажем, `runtest', сделайте
его исполняемым (chmod +x runtest
) и запустите его из оболочки
Unix:
$ ./runtest Program loaded. Start address: 3000 Running ... ... done Elapsed time: 190908 /Total program time: 190908 (Total uptime: 190908) rA: + 30 30 30 30 30 (0511305630) rX: + 30 30 32 32 39 (0511313959) rJ: + 47 18 (3026) rI1: + 00 00 (0000) rI2: + 55 51 (3571) rI3: + 00 19 (0019) rI4: + 31 51 (2035) rI5: + 00 00 (0000) rI6: + 00 00 (0000) Overflow: F Cmp: L $ |
Заметьте, что это гораздо более гибкий способ, чем неинтерактивный
запуск программ с помощью mixvm
(see section 3.3.1 Неинтерактивный режим),
поскольку в скрипте Scheme вы можете использовать любое сочетание команд
(а не только выполнение программы и просмотр регистров). Дополнительные
параметры командной строки mixguile
см. в 8.1 Вызов mixguile
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
3.5 Использование Scheme в mixvm
и gmixvm
В предыдущем разделе (see section 3.4 Использование mixguile
) мы рассмотрели
возможности использования Scheme для управления виртуальной машиной MIX
и расширения набора команд mixvm
и gmixvm
, предлагаемые
оболочкой Guile mixguile
. Эти возможности не ограничены оболочкой
mixguile
. На самом деле, и mixvm
, и gmixvm
включают
встроенный интерпретатор Guile и могут вычислять выражения Scheme.
Чтобы вычислить выражение из одной строки в приглашении mixvm
или
gmixvm
, просто введите его и нажмите клавишу ввода (анализатор команд
распознает, что это выражение Scheme, поскольку оно заключено в скобки, и
передаст его интерпретатору Guile). Пример сеанса работы с использованием
выражений Scheme:
MIX > load hello Program loaded. Start address: 3000 MIX > (define a (mix-loc)) MIX > run Running ... MIXAL HELLO WORLD ... done Elapsed time: 11 /Total program time: 11 (Total uptime: 11) MIX > (mix-pmem a) 3000: + 46 58 00 19 37 (0786957541) MIX > (mix-pmem (mix-loc)) 3002: + 14 09 27 01 13 (0237350989) MIX > |
Вы можете также загрузить и выполнить файл командой scmf
:
MIX> scmf /path/to/file/file.scm |
Поэтому при работе в mixvm
и gmixvm
в вашем распоряжении
находятся все описанные выше возможности mixguile
(новые функции,
определения новых команд, ловушки...). Другими словами, эти программы
можно расширять с помощью Scheme. Примеры этого см. в 3.4 Использование mixguile
.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on June, 9 2003 using texi2html