2023-09-10

vak: (Default)
Начитавшись книжки Кнута про архитектуру MMIX, взялся я это дело попрограммировать. Перефразируя Чичикова, давненько не брал я в руки шашек ассемблера. Но вместо кнутовского mmixal задействуем GNU assembler. Он максимально повторяет стандартный синтаксис для MMIX, но в несколько более современном стиле. Где скачать или как собрать GCC тулчейн для MMIX я уже как-то рассказывал.

Адаптируем для GNU ассемблера стандартный пример hello.mms. Получается такой файл hi.S:
#define Halt    0
#define Fputs 7
#define StdOut 1

.text
.global _init
_init LDA $255, text // Put address of text message into register $255
TRAP 0, Fputs, StdOut // System call Fputs()
SET $255, 0 // Exit code
TRAP 0, Halt, 0 // System call Halt()

.section .rodata
text .asciz "Hi, GNU assembler!\n"
Компилируем:
$ mmix-gcc -nostdlib hi.S -o hi
Запускаем с трассировкой:
$ mmix -t2 hi
1. 0000000000000100: 23fffe00 (ADDUI) $255=g[255] = 272 = #110
Hi, GNU assembler!
1. 0000000000000104: 00000701 (TRAP) $255 = Fputs(StdOut,#110) = 19
1. 0000000000000108: e3ff0000 (SETL) $255=g[255] = #0
1. 000000000000010c: 00000000 (TRAP) Halt(0)
4 instructions, 0 mems, 12 oops; 0 good guesses, 0 bad
(halted at location #000000000000010c)
В следующий раз надо будет что-нибудь более сложное сварганить.

Справочник по системе команд MMIX, для интересующихся: mmix.cs.hm.edu/doc/instructions-en.html
vak: (Default)
Я вижу, MMIX вызвал интерес. Вот вам вдогонку пара чуть более сложных примеров на GNU ассемблере.

echo

Классическая юниксная утилита /bin/echo: печатает в строчку свои аргументы. При старте программа получает количество аргументов в регистре $0, а адрес таблицы аргументов - в регистре $1. Файл echo.S:
#define Halt    0
#define Fputs   7
#define StdOut  1

#define argc    $0
#define argv    $1

        .text
        .global _init
_init   SUB     argc, argc, 2       // decrement argc by 2
        PBNN    argc, 2F            // if argc >= 0 - enter loop
        JMP     9F                  // otherwise skip the loop

1H      LDA     $255, Blank         // get address of blank string
        TRAP    0, Fputs, StdOut    // print space
        SUB     argc, argc, 1       // decrement argc
        ADD     argv, argv, 8       // increment argv
2H      LDOU    $255, argv, 8       // get address of argument
        TRAP    0, Fputs, StdOut    // print argument
        PBNZ    argc, 1B            // if arc != 0 - next iteration
9H      LDA     $255, NewLine       // get address of newline string
        TRAP    0, Fputs, StdOut    // print newline
        SET     $255, 0             // exit code
        TRAP    0, Halt, 0          // terminate

        .section .rodata
Blank   .asciz  " "  
NewLine .asciz  "\n"
Компилируем, запускаем:
$ mmix-gcc -nostdlib echo.S -o echo
$ mmix echo foo bar
foo bar

primes

Вычисляем первые 500 простых чисел. Файл primes.S: