Описывается модификация транслятора ЛЯПАС для возможности разработки операционной системы. Изменены инициализирующий и завершающий ассемблерные коды, скорректирована работа с комплексами, оптимизировано использование памяти программой, добавлены новые возможности: доступ к произвольной ячейке оперативной памяти и получение адреса процедур.
Modification of lyapas for operating systems development.pdf Разработка операционной системы (ОС) предъявляет к языку программирования и компилятору с него ряд специфических требований, например необходимость хранения служебных структур данных на протяжении всего времени работы ОС, возможность записи адресов подпрограмм в переменные языка, возможность генерирования ассемблерного кода без привязки к существующей ОС, в которой ведётся разработка, и к её формату исполняемого файла. В данной работе сообщается о модификации Логического Языка для Представления Алгоритмов Синтеза (ЛЯПАСа) [1] и соответствующего транслятора для разработки ОС [2]. Кроме упомянутых изменений, в язык добавлены возможности, повышающие удобство разработки программ на нём, а в компилятор - повышающие надёжность генерируемой ассемблерной программы. Для работы операционной системы необходимо хранить некоторые структуры данных от запуска компьютера до его выключения. Примерами таких структур являются глобальная таблица дескрипторов (GDT), таблица дескрипторов прерываний (IDT) [3], таблица планировщика процессов. Однако в ЛЯПАСе отсутствуют глобальные переменные, обычно применяемые для данных целей, поэтому в язык добавлен доступ к произвольной ячейке оперативной памяти. Такой доступ осуществляется через специальный комплекс K, i-й элемент которого представляет собой ячейку оперативной памяти по адресу i. Дополнительно это позволяет выводить сообщения на экран, производя их запись в участок памяти с фиксированным адресом - видеобуфер. Для построения IDT введена возможность получения адресов подпрограмм. Во внутреннюю переменную т помещается адрес ассемблерной метки, с которой начинается подпрограмма. Перечисленные возможности считаются потенциально небезопасными для разработки пользовательских программ и включаются при трансляции флагом -os. Для компиляции файла, запускаемого в ОС GNU/Linux, транслятор добавляет инициализирующий и завершающий коды. Инициализирующий код запрашивает у ОС память под комплексы в куче, переходит на первую подпрограмму, после завершения выполняет системный вызов sys_exit; завершающий код содержит подпрограмму _addmem, которая запрашивает дополнительную память в куче. Изменение инициализирующего и завершающего кодов включается флагом -os. 8 Дополнительно к описанным в ЛЯПАС внесены изменения, делающие язык более удобным. Во-первых, в работе с комплексами добавлена проверка по ёмкости. При обращении к i-му элементу комплекса ёмкостью S проверяется условие i < S. Если оно не выполняется, программа переходит на метку _errend. Во-вторых, оптимизировано использование памяти программой. Ранее в ЛЯПАСе для каждой вызываемой подпрограммы в стеке выделялось 1420 байт под все возможные локальные переменные, параметры всех возможных комплексов (тип комплекса, адрес комплекса в куче, ёмкость, мощность), адрес начала свободной памяти в куче. Адреса локальных переменных фиксировались в стеке в соответствии с их именами: вызывающая подпрограмма выделяла память в стеке для вызываемой, помещала туда входные параметры, копировала значения выходных параметров после завершения подпрограммы. Данный способ прост в реализации, однако неэффективно использует память и создаёт много вспомогательных конструкций в коде. Предлагаются следующие изменения. Память выделяется только под используемые локальные переменные; переменные и комплексы размещаются в стеке в порядке их упоминания, что позволяет намного эффективнее использовать память. Вызывающая подпрограмма выделяет память в стеке для входных и выходных параметров вызываемой подпрограммы, заполняет входные параметры и отдаёт управление вызываемой. Последняя самостоятельно выделяет память в стеке под локальные переменные, а после завершения работы удаляет их. После этого вызывающая подпрограмма копирует значения выходных параметров в свои локальные переменные и возвращает стек к исходному состоянию. Новая организация памяти программы позволяет также реализовать эффективную композицию подпрограмм. Обозначим множество значений переменных V, множества значений символьных и логических комплексов F и L соответственно. Тогда каждая подпрограмма соответствует функции из декартова произведения, составленного из V, F, L, в другое декартово произведение, составленное аналогичным образом. Например, подпрограмма с заголовком f (c, a, L1, F3/b, L2) соответствует функции f : V х V х L х F ^ V х L. Будем говорить, что существует композиция подпрограмм f и g, если существует композиция соответствующих функций. Значения входных и выходных параметров подпрограммы будем называть входными и выходными значениями подпрограммы соответственно. Ранее в языке для получения значения (gf )(а) композиции подпрограмм f и g необходимо было вызвать подпрограмму f на a, скопировать её выходные значения в локальные переменные, подать их на вход функции g и получить её выходные значения. При новой организации памяти можно реализовать более эффективную композицию подпрограмм. Для этого после завершения работы одной подпрограммы стек не возвращается к исходному состоянию, выходные значения завершённой подпрограммы становятся входными значениями следующей в композиции подпрограммы, в стеке выделяется память под выходные значения последней, после чего происходит её вызов. Это позволяет избежать лишнего копирования данных и использования локальных переменных для передачи значений с выхода одной подпрограммы на вход другой. В ЛЯПАСе вызов функции обозначается следующим образом: *f (in/out), где f - имя подпрограммы; in - список входных значений; out - список выходных значений. Для удобства чтения и понимания программ на ЛЯПАСе композиция обозначена схожим образом: *fn *fn-i ...*fi (ini/outn), где fi, ..., fn - названия подпрограмм; in1 - входные значения первой подпрограммы; outn - выходные значения последней. При этом компилятор проверяет существование композиции подпрограмм. Для увеличения числа возможных композиций подпрограмм предлагается зафиксировать порядок перечисления входных и выходных параметров: сначала описываются параметры-переменные, затем - параметры-логические комплексы, затем - параметры-символь-ные комплексы. Эта особенность языка будет полезна при создании крупных библиотек на ЛЯПАСе.
Гречнев Сергей Юрьевич | Национальный исследовательский Томский государственный университет | студент кафедры защиты информации и криптографии | sgrechnev@gmail.com |
Стефанцов Дмитрий Александрович | Национальный исследовательский Томский государственный университет | старший преподаватель кафедры защиты информации и криптографии | d.a.stefantsov@isc.tsu.ru |
Intel 64 and IA-32 Architectures Software Developer Manuals http://www.intel.com/ content/www/us/en/processors/architectures-software-developer-manuals.html
Стефанцов Д. А., Томских П. А. Разработка операционной системы на языке ЛЯПАС // Прикладная дискретная математика. Приложение. 2015. №8. С. 134-135.
Агибалов Г. П., Липский В. Б., Панкратова И. А. О криптографическом расширении и его реализации для русского языка программирования // Прикладная дискретная математика. 2013. №3. С. 93-104.