ESM - VM, asembler, linker and disassembler
Esm Assembly Language - это эзотерический asm-подобный язык. В нём есть 16 команд:
axc
- сдвинуть регистр A на 4 бита влево, затем побитово сложить с аргументом (4 бита). Пример:
axc 1011
mov
- скопировать значения второго регистра в первый. Пример:
mov C B
loa
- заменить младший байт первого регистра байтом в виртуальной памяти по адресу, задаваемому вторым регистром
sto
- заменить младшим байтом первого регистра байт в виртуальной памяти по адресу, задаваемому вторым регистром
and
- побитовое И между двумя регистрами, результат сохранить в первом регистре
orb
- побитовое ИЛИ между двумя регистрами, результат сохранить в первом регистре
xor
- побитовый XOR между двумя регистрами, результат сохранить в первом регистре
add
- сложить два регистра, результат сохранить в первом регистре
jmp
(безусловный переход) - перейти к выполнения инструкций по адресу, задаваемом вторым регистром (первый игнорируется, в коде нужно указать только второй регистр, например jmp D
)
jgz
(условный переход) - выполнить jmp на второй регистр, если значение первого (строго) больше 0
cmp
- сравнить два регистра, если r1 (значение первого регистра) == r2, то поместить в первый регистр 0, если r1 < r2, то 1, если r1 > r2, то 2
lsh
- побитовый сдвиг первого регистра на число бит, задаваемое вторым регистром, результат сохранить в первом регистре
put
- вывести символ с ASCII-кодом, равным младшему байту первого регистра (второй регистр в коде указывать не нужно)
get
- считать символ, заменить его ASCII-кодом младший байт первого регистра (второй регистр в коде указывать не нужно)
xrx
(не рекомендован) - поменять местами значения первого регистра и скрытого регистра X (второй регистр в коде указывать не нужно). Не рекомендован, ибо планируется заменить командой системного вызова
stp
- выйти из программы, код завершения - младшие 4 байта первого регистра (второй регистр в коде указывать не нужно)
Все команды, кроме одной, записываются в виде:
cmd R1 R2
, где cmd
- это одна из команд, R1
и R2
- одни из регистров A
, B
, C
и D
(команды чувствительны к регистру символов, имена регистров -
нет). Если команда требует только один регистр, то указывать нужно только один.
В одной строке можно записать только одну команду.
Единственное исключение - команда axc
. Она записывается в виде:
axc CONST
, где CONST
- это строка из символов '0' и '1' длиной 4. Пример:
axc 0100
Комментарии начинаются с символа '#', сразу за которым следует пробел
esmvm - регистровая виртуальная машина, операции выполняются над регистрами. Существуют 5 регистров: A (00), B (01), C (10), D (11), X (-). В скобках показаны двоичный представления этих регистров ("-" означает, что такого представления нет). Всего существует 16 команд, каждая кодируется 4 битами.ъ Таким образом, каждая команда с аргументами влезает в 1 байт.
Если вы дочитали досюда, то мне вас жаль я вас поздравляю.
Мне писать дальше лень.
~ $ git clone https://github.com/kodo-pp/esm-vm
Cloning into 'esm-vm'...
< ... >
Checking connectivity... done.
~ $ cd esm-vm
~/esm-vm $ ./build.sh
< ... >
~/esm-vm $ sudo ./install.sh /usr/bin
[sudo] password for user:
< ... >
~/esm-vm $ which esmvm
/usr/bin/esmvm
~/esm-vm $ cd ~
~ $ ls -F
esm-vm/
~ $ # Write a simple program
~ $ cat << EOF > test.ecs
axc 0010
axc 1010
stp A
EOF
~ $ cat test.ecs
xor A A
axc 0010
axc 1010
stp A
~ $ ls -F
esm-vm/
test.ecs
~ $ # Assemble
~ $ esms test.ecs test.ecc
~ $ ls -F
esm-vm/
test.ecc
test.ecs
~ $ # Link with data (no data in our case, 10 is position to put data to, 'test.ex' - final executable)
~ $ esmputdata test.ecc /dev/null test.ex 10
~ $ ls -F
esm-vm/
test.ecc
test.ecs
test.ex
~ $ # Run our program
~ $ esmvm test.ex
~ $ echo $?
42
~ $ # yes, our exit status is 42 (42 == 0b101010)
~ $ # And, finally, disassemble
~ $ esmdump test.ex
# Data located at 10
# Code ends at 4
xor A A
axc 0010
axc 1010
stp A
# <code ends>
~ $ # So, everything is working fine