Node:Написание исходного файла, Next:, Previous:Начало работы, Up:Начало работы



Написание исходного файла

Программы на 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)

При использовании утилит MDK исходным файлам MIXAL следует давать расширение .mixal. Как вы можете видеть в этом примере, каждая строка в файле MIXAL может быть разделена на четыре поля, разделённые любым количеством пробельных символов (пробелы и знаки табуляции). В определении MIXAL Кнута каждое поле должно начинаться в фиксированной колонке, но ассемблер MDK ослабляет это требование и позволяет форматировать файл по вашему усмотрению. Ограничения связаны только со строками комментариев (такими, как 1-4), которые должны начинаться со звёздочки (*), помещённой в первой колонке, и с полями меток (см. ниже), которые, если они присутствуют, также должны начинаться в первой колонке. Четыре поля, присутствующие в каждой строке, не являющейся комментарием, это:

Строки 9-12 в файле hello.mixal показываеют также второе (и последнее) различие между определениями MIXAL Кнута и нашими: операнд псевдоинструкции ALf (слово из пяти литер) должно быть заключено в двойные кавычки2.

Если вы знакомы с MIXAL, работа этого примера программы должна быть понятна. См. полное определение MIXAL в томе 1 "Искусства программирования", учебник - Учебник по MIX и MIXAL.


Footnotes

  1. Если директива ORIG не используется, программа будет загружена виртуальной машиной по адресу 0. ORIG позволяет расположить исполняемый код по вашему усмотрению.

  2. В определении Кнута операнд всегда начинается с фиксированной колонки, и поэтому использование кавычек необязательно. Поскольку mixasm не содержит этого ограничения, для устранения неоднозначности разбора этого операнда в случаях, когда он содержит пробелы, используются кавычки. Имейте в виду, что двойные кавычки не входят в набор литер MIX, и поэтому экранировать литеры внутри операндов ALF не нужно.


Node:Определение новых функций, Next:, Previous:Дополнительные функции, Up:Использование mixguile



Определение новых функций

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.

Node:Дополнительные функции ВМ, Previous:Ловушки, Up:Описание функций Scheme



Дополнительные функции ВМ

При написании нетривиальных расширений Scheme с использованием библиотеки MIX/Scheme, вам, вероятно, будет нужно определять содержимое компонентов виртуальной машины (регистры, ячейки памяти и т.д.). Например, вам может понадобиться сохранить содержимое регистра A в переменной. Функции Scheme, описанные до сих пор, не помогут - вы можете вывести содержимое A функцией (mix-preg 'A), но не можете присвоить значение A переменной. Для решения этой проблемы библиотека MIX/Scheme предоставляет следующие дополнительные функции:

mixvm-status Function
mix-vm-status Function
Возвращает текущий статус виртуальной машины в виде числа (mixvm-status) или символа (mix-vm-status). Возможные возвращаемые значения:

(mixvm-status) (mix-vm-status)
0 MIX_ERROR Ошибка загрузки или выполнения
1 MIX_BREAK Обнаружена точка останова
2 MIX_COND_BREAK Условная точка останова
3 MIX_HALTED Выполнение прервано
4 MIX_RUNNING Выполнение по next остановлено
5 MIX_LOADED Программа успешно загружена
6 MIX_EMPTY Программа не загружена

mix-vm-error? Function
mix-vm-break? Function
mix-vm-cond-break? Function
mix-vm-halted? Function
mix-vm-running? Function
mix-vm-loaded? Function
mix-vm-empty? Function
Предикаты, проверяющие равенство текущего статуса виртуальной машины MIX_ERROR, MIX_BREAK и т.д.

mix-reg register Function
mix-set-reg! register value Function
mix-reg возвращает содержимое указанного регистра в виде числа. mix-set-reg приравнивает значение указанного регистра заданному. Регистр может быть задан либо в виде строки ("A", "X" и т.д.), либо в виде символа ('A, 'X и т.д.). Например:
guile> (mix-reg 'A)
2341
guile> (mix-set-reg! "A" 2000)
ok
guile> (define reg-a (mix-reg 'A))
guile> (display reg-a)
2000
guile>

mix-cell cell_no Function
mix-set-cell! cell_no value Function
Возвращает и устанавливает содержимое ячейки памяти номер cell_no соответственно. И cell_no, и value - числа Scheme.

mix-loc Function
Возвращает значение счётчика положения (т.е. адрес следующей выполняемой инструкции).

mix-over Function
mix-set-over! #t|#f Function
mix-over возвращает #t, если триггер переполнения установлен, и #f в противном случае. Значение триггера переполнения может быть изменено функцией mix-set-over!.

mix-cmp Function
mix-set-cmp! 'L|'E|'G Function
Возвращает и устанавливает флаг сравнения соответственно. Возможные значения - символы Scheme L (меньше), E (равно) и G (больше).

mix-up-time Function
Возвращает текущее время работы виртуальной машины.

mix-lap-time Function
Возвращает текущее прошедшее время виртуальной машины, т.е. время, прошедшее после последней команды run или next.

mix-prog-time Function
Возвращает общее время выполнения загруженной в данный момент программы.

mix-prog-name Function
Возвращает строку, содержащую базовое имя (без пути) загруженной в данный момент программы MIX.

mix-prog-path Function
Возвращает строку, содержащую полный путь к загруженной в данный момент программе MIX.

mix-src-path Function
Возвращает строку, содержащую полный путь к исходному файлу загруженной в данный момент программы MIX.

mix-src-line [lineno] Function
mix-src-line-no Function
mix-src-line-no во время выполнения программы возвращает номер текущей строки исходного кода. mix-src-line возвращает строку, содержащую строку исходного файла номер lineno, а при вызове без аргументов возвращает (mix-src-line (mix-src-line-no)).

mix-ddir Function
Возвращает строку, содержащую полный путь к текущему каталогу устройств.