Новости
Описание
Текущая версия
История
Скриншоты
OS Menuet
Дистрибутивы
Загрузчики
Программы
Статьи
FAQ
Hardware List
Рассылки
Наша команда
Публикация
Конкурс
Форум
О Menuet
Другие OS
Программисту
|
|
|
|
Использование C-- при написании программ под MenuetOS.
|
Начнем с формата исполняемого файла. Как известно для MeOS это
flat-файл, имеющий определенный заголовок, вот он перед вами для
компилятора fasm:
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd I_END ; size of image
dd 0x100000 ; memory for app
dd 0x7fff0 ; esp
dd 0x0 , 0x0 ; I_Param , I_Icon
А это совершенно ни чем не уступающий ему эквивалент декларации на
C-, и даже помоему более понятный:
#pragma option LST // Включим генерацию листинга
#pragma option OC // Оптимизация кода на размер
#pragma option J0 // Убираем стартовый JMP MAIN
#pragma option 4 // Устанавливаем генерацию кода под 0x80486
#pragma option A // Установка выравнивания кода
#startaddress 0 // Смещение в сегменте 0 (аналог org 0x0)
#code32 TRUE // Генерация 32 р-ого кода
char os_name[8] = {'M','E','N','U','E','T','0','1'};
dword os_version = 0x00000001;
dword start_addr = #main;
dword final_addr = #stop;
dword alloc_mem = 0x00100000;
dword x86esp_reg = 0x0007fff0;
dword I_Param = 0x0;
dword I_Icon = 0x0;
Заголовок следует по смещению 0 от начала файла (fasm org 0x0), что
благодаря Михаилу Шеккеру достаточно просто сделать для встроеннного
линкера C--, следующей строчкой (хочу обратить сразу ваше внимание на
то что очень много настраиваемых параметров в C-- вынесены на уровень
деректив и опций трансляции).
Тепепер необходимо обрамить функции API MenuetOS inline функция, такие функции в C-- вставляются непосредственно в код (хотя есть ключ заставляющий генерировать их вызов командой call), превожу как пример вызов функции выхода
из процесса и функцию ожидания события, возращающую значение:
inline fastcall dword WaitEvent(){
#speed
EAX = 10; // wait here for event
$int 0x40
#codesize
}
Любая функция в C-- возращает значение через регистр EAX,AX,AL в зависимости от типа возращаемого значения DWORD, WORD, BYTE, соответственно. Определение fastcall в заголовке функции запрещает компилятору генерировать стандартный frame для размещения локальных переменных и делать любые манипуляции с кодом в начале функции и ее конце. Т.е. приведенная выше функция есть ни что иное как фрагмент в ассемблере
mov eax, 10;
int 0x40;
Поскольку функция inline генерация ret не производится.
#speed - ключ трансляции затсавляющий компилятор генерировать быстрый код, в противном случае передача значения в регистр была бы выполнена через стэк:
push 10 ; Операнд 10 есть байт расширяемый в стеке до dword
pop eax
Все эти нюансы легко расмотреть в формируемом LST файле выглядищим сл. образом:
menuet.h-- 71: EAX = 10; // wait here for event
00000029 B80A000000 mov eax,0Ah
menuet.h-- 72: $int 0x40
0000002E CD40 int 40h
inline fastcall void ExitProcess(){
#speed
EAX = -1; // close this program
$int 0x40
#codesize
}
Я специально оставил не оптимизированый код, что бы это выглядело как у Вилле, хотя гораздо быстрее и короче сделать так:
EAX = 0; // В этом случае компилятор ставит XOR EAX,EAX
EAX-- ;
,или так:
EAX = 0 - 1; // Запись выражения в C-- нестандартная нотация, а последовательность действий с лево на право.
Желательно проверять по листингу реальный размер кода, так
компилятор может вставить за меткой stop, необходимые ему служебные
таблицы потому заголовок приложения, не будет реально
соответствовать длине, потому необходимо держать на контроле
значение метки #stop. Кое-какие опцию могут помочь избавиться от
части кода которую компилятор может поместить за меткой stop.
#align 16
#setdinproc
#align 16
stop:
Данная последовательность заставляет макро-процедуры c--
(динамически вставляемый код при его вызове, для C-- это процедуры
имеющие : перед именем) вставляться в месте указанном #setdinproc.
Но таблицы jmp от case могут так-же расположиться за меткой stop,
пока ничего лучше вот этого я не придумал:
char os_name[8] = {'M','E','N','U','E','T','0','1'};
dword os_version = 0x00000001;
dword start_addr = #main;
dword final_addr = #stop+32;
^^^^^^^^Заранее определяем некую глубину конца кода.
dword alloc_mem = 0x00100000;
dword x86esp_reg = 0x0007fff0;
dword I_Param = 0x0;
dword I_Icon = 0x0;
Надеюсь Вы оцените всю мощь языка и компилятора, сайт которого находится по адресу www.sheker.narod.ru
Искренне Ваш, Алексей Сугоняев.
Email: alexey_s@ezmail.ru
|
|