Mkxm2cc
Эта страница предлагается для быстрого удаления. Причина: У1: по желанию владельца страницы. Пояснение: репозиторий с библиотекой mkxm2cc удалён, mkxm2cc устарел.
Страница сохранена 10704 минуты назад. Администраторам: ссылки сюда, история (последнее изменение), удалить.
|
Введение[править]
Эта книга повествует о написании программ под операционную систему Xmtwolime, используя возможности языка Си.
Mkxm2cc — это изменённый Си, предназначенный для написания программ под виртуальную машину iiixmish2.[1]
Сборка mkxm2cc-программы (которая написана для Xmtwolime)[1]:
- компиляция Си-компилятором
- запуск полученной программы с перенаправлением stdout в xmtwolime/software/имя_программы.s
- удаление программы, которая была получена после шага 1
Требования[править]
Пожалуйста, прочтите учебник по Xmtwolime. Заголовочные файлы библиотек можно поместить в /usr/include. Нужно иметь знания о языке программирования Си.
Первая программа[править]
Создайте файл hey.c со следующим содержимым:
#include <xmtwolime_mkxm2cc.h>
int main(void) {
init("hey");
aprint("Hello, world!", _OUT_ST);
exit_app(EXIT_SUCCESS);
}
Это mkxm2cc-программа. Соберите её, а после систему. Запустите Xmtwolime, наберите в оболочке имя программы («hey»; оно должно быть длиной в три ASCII-символа), на экране должно появиться «Hello, world!».
Разбор кода[2][править]
#include <xmtwolime_mkxm2cc.h>[править]
Это включает содержимое файла xmtwolime_mkxm2cc.h, содержащего главную библиотеку mkxm2cc для Xmtwolime-программ.
init("hey")[править]
Это вызывает функцию init(). Она должна быть первой функцией, которая вызывается в Вашей программе. «hey» — это имя программы.
aprint("Hello, world!", _OUT_ST)[править]
Это ложит ASCII-строку «Hello, world!» в видеопамять, начиная с _OUT_ST. Данная функция использует команду VSTR
.
exit_app(EXIT_SUCCESS)[править]
Успешное завершение программы. Не забывайте использовать exit_app() или mexit_app(), чтобы завершить приложение и вернуть пользователя к оболочке!
Им. константы, которые следует знать[править]
Название | Описание |
---|---|
_BLACK, _WHITE, _GREEN, _BLUE, _GREEN2, _GREY, _RED, _YELLOW | коды цветов |
_XREG | п. регистр, который используется, например, функцией xprint() |
_EQ, _NE, _GT, _LT | операторы для вставки в ifmm() и ifmn() |
_R_USER | п. регистр, содержащий текущий UID |
_ARGS_ST | начало аргументов программы в видеопамяти |
_OUT_ST | начало вывода программы в видеопамяти |
_ORDINARY_USER_SPACE_ST | начало данных пользователя в памяти |
_LINE_SIZE | длина строки |
Переменные[править]
Используйте alloc() для статического выделения памяти:
int var = alloc(1); // целое число
addr_t array = alloc(64); // array равен началу массива, в котором 64 элемента
Код free_mem(16)
аналогичен alloc(-16)
.
Метки[править]
Всегда начинайте имена своих меток с названия программы! |
Функции | Описание |
---|---|
int L(char *_name) |
создание метки |
int G(char *_target) и int Gm(uint32_t _maddr_with_target) |
переход к _target (оно может быть либо mov2-числом, либо <меткой>) или к [значение ячейки _maddr_with_target] |
Работа с памятью[править]
Не передавайте параметры-числа mkxm2cc-функциям, если в них больше семи цифр! |
Функции | Описание |
---|---|
int neg(uint32_t _addr) и int negm(uint32_t _maddr_with_addr) |
изменить знак ячейки памяти; _maddr_with_addr должен быть адресом к ячейке памяти, которая содержит адрес |
int mset(uint32_t _addr, uint32_t _value) и int simple_mset(uint32_t _addr, char _value) |
изменить содержимое ячейки памяти |
int msetl(uint32_t _addr, char *_value) |
изменить содержимое ячейки памяти; _value может иметь форму «<МЕТКА>» (набирать точно так, как показано, кроме «МЕТКА») |
int mfill(uint32_t _addr, int _v, size_t _s) |
заполнить _s ячеек памяти числом _v, начиная с _addr |
int mfill2(char *_start, int _v, char *_end) |
заполнить память числом _v от _start до _end; они могут иметь форму <меток> (например, «<abc_endif0>») |
int mcopy(uint32_t _addr_src, uint32_t _addr_dst) , int mcopymn(uint32_t _maddr_with_srcaddr, uint32_t _addr_dst) , int mcopynm(uint32_t _addr_src, uint32_t _maddr_with_dstaddr) , int mcopymm(uint32_t _maddr_with_srcaddr, uint32_t _maddr_with_dstaddr) , int mcopyll(char *_labeloraddr_src, char *_labeloraddr_dst) , int mcopyln(char *_labeloraddr_src, uint32_t _addr_dst) , int mcopynl(uint32_t _addr_src, char *_labeloraddr_dst) |
копировать содержимое одной ячейки памяти в другую; примеры: mcopymn(var, 8700001) копирует содержимое ячейки памяти, адрес которой находится в var, в яч. 8700001; mcopyll("<label1>", "<label2>") копирует содержимое ячейки <label1> в ячейку <label2>
|
size_t w_str(char *_s, uint32_t _startaddr) |
записать строку _s в память, начиная с ячейки _startaddr; возвращает длину строки |
int inc(uint32_t _addr) и int dec(uint32_t _addr) |
инкремент и декремент |
int strv(uint32_t _startvaddr, uint32_t _startmaddr, size_t _n) |
скопировать _n символов из видеопамяти, начиная с _startvaddr, в память, начиная с _startmaddr |
int gen(uint32_t _max, uint32_t _dst_addr) |
генерация числа не больше _max и копирование его в память |
int calcmm(uint32_t _addr1, char _op, uint32_t _addr2, uint32_t _resultaddr) и int calcmn(uint32_t _addr1, char _op, uint32_t _num, uint32_t _resultaddr) |
выполнение операции (сложение, вычитание, получение остатка от деления, деление, умножение, возведение в степень — '+', '-', '%', '/', '*', '^') над числами и сохранение результата в память; пример: calcmn(sum, '-', 2, sum) вычитает 2 из ячейки памяти sum и сохраняет результат в неё
|
int catv(uint32_t _startaddr, uint32_t _resultaddr, uint32_t _num) |
если _num равно 48: копировать число-строку из памяти в формате ЦЦЦЦЦЦ (например, 000129), начиная с _startaddr, в ячейку памяти _resultaddr; MT-Unsafe |
int catv2(uint32_t _startaddr, uint32_t _resultaddr) |
копировать число-строку из памяти в формате {-/ }ЦЦЦЦЦЦЦ («-0000129 », « 8700000 »…), начиная с _startaddr, в ячейку памяти _resultaddr; MT-Unsafe
|
Работа с пользовательскими регистрами[править]
int getreg(uint8_t _reg, uint32_t _maddr)
и int toreg(uint32_t _maddr, uint8_t _reg)
— загрузить п. регистр в память и обратно.
Функции xset(uint32_t), xinc() и xdec() выполняют действия над п. регистром _XREG.
Паузы[править]
slp(5)
останавливает выполнение программы на пять секунд, mslp(var)
делает паузу на столько секунд, сколько указано в ячейке памяти var. Для задержки в миллисекундах, используйте uslp() и muslp().
Ввод/вывод[править]
Функции | Описание |
---|---|
int aprint(char *_s, uint32_t _addr) |
напечатать ASCII-строку |
int get_c(uint32_t _vaddr, uint32_t _maddr) |
копировать символ из видеопамяти в память; сперва, указывается адрес в видеопамяти |
int get_key(uint32_t _maddr) |
копировать нажатую клавишу в память |
int get_char(int _maddr) |
ждать символ от пользователя и положить его в ячейку _maddr |
int setcolor(uint8_t _bg, uint8_t _other) |
установить цвет фона и текста |
int put_c(uint32_t _c, uint32_t _vaddr) |
записать символ _c в видеопамять |
int put_mc(uint32_t _maddr, uint32_t _vaddr) |
записать содержимое ячейки памяти _maddr в ячейку видеопамяти _vaddr |
int put_mcm(uint32_t _maddr, uint32_t _maddr_with_vaddr) |
записать содержимое ячейки памяти _maddr в ячейку видеопамяти, адрес которой хранится в яч. памяти _maddr_with_vaddr |
int vclear() |
стереть почти всю видеопамять; исопльзует команду VRST
|
int xprint(char *_s, int _color) |
поместить строку в видеопамять с цветом _color (если он не ниже нуля), начиная со значения п. регистра _XREG |
int xprintm(uint32_t _startaddr, size_t _size, int _color) |
аналогично предыдущей функции, но строка имеет длину _size и хранится в памяти, начиная с _startaddr |
int xerr(char *_msg) |
xprint(_msg, _RED) |
int xwarn(char *_msg) |
xprint(_msg, _YELLOW) |
Функции put_n(), put_mn() и put_mnm(), подобны put_c(), put_mc() и put_mcm(), но они печатают «как число». Так, put_n(10, _OUT_ST + _LINE_SIZE)
отобразит число десять на экран, начиная с яч. видеопамяти _OUT_ST + _LINE_SIZE. Функция upddisp() обновляет экран (используйте после put_c(), put_n()…). vcatv() и vcatv2() аналогичны catv() и catv2(), но число-строка должна быть в видеопамяти.
Задание
Перепишите первую программу так, чтобы она использовала xprint() вместо aprint()
Ветвление[править]
Условия в mkxm2cc создаются посредством ifmn(), ifmm(), mcomp() и vcomp().
Образец конструкции представлен ниже:
функция_ветвления(…, "<Метка>");
код
L("Метка");
Функции[править]
Функция | Описание |
---|---|
int ifmm(uint32_t _addr1, char *_op, uint32_t _addr2, char *_else_start) |
сравнивает ячейки памяти _addr1 и _addr2, и, если проверка оказалась неудачна, переходит к _else_start; _op может быть "==", "!="
, ">" или "<" |
int ifmn(uint32_t _addr1, char *_op, uint32_t _num, char *_else_start) |
сравнивает ячейку _addr1 с числом _num, и, если проверка оказалась неудачна, переходит к _else_start |
size_t mcomp(uint32_t _addr, char *_s, char *_else_start) |
сравнивает строку в памяти, начиная с _addr, со строкой _s, и, если проверка оказалась неудачна, переходит к _else_start |
size_t vcomp(uint32_t _addr, char *_s, char *_else_start) |
сравнивает строку в видеопамяти, начиная с _addr, со строкой _s, и, если проверка оказалась неудачна, переходит к _else_start |
Безопасность[править]
Безопасность Xmtwolime и безопасность программ сильно связаны. Программы находятся в разделе system и имеют полный доступ к памяти, независимо от текущего UID. Создавайте безопасные программы!
Многопоточность[править]
int new_thrd(void *_function(), uint8_t _num)
[править]
Данная функция «выполняет» _function в новом потоке _num. Не рекомендуется устанавливать _num отличным от 1.
Продолжаем изучение[править]
NOPS(_n)
вставляет _n команд nop
. Функция reboot() выполняет полную перезагрузку системы. halt() останавливает текущий поток.
exit_app(0)
завершит программу с кодом 0. mexit_app(c)
завершит программу с кодом, который хранится в ячейке c.
Программа ech.c[править]
#include <xmtwolime_mkxm2cc.h>
int main(void) {
init("ech");
addr_t args = alloc(_OUT_ST - _ARGS_ST);
strv(_ARGS_ST, args, _OUT_ST - _ARGS_ST);
xprintm(args, _OUT_ST - _ARGS_ST, -1);
exit_app(0);
}