OS Menuet
 Новости
 Описание
 Текущая версия
 История
 Скриншоты

Скачать
 OS Menuet
 Дистрибутивы
 Загрузчики
 Программы

Документация
 Статьи
 FAQ
 Hardware List
 Рассылки

О нашем сайте
 Наша команда
 Публикация
 Конкурс
 Форум

Ссылки
 О Menuet
 Другие OS
 Программисту

Официальный сайт/Official site MenuetOS>>
Использование 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;

    Прилагаю компилятор, которым я генерировал код примера example.c--
    Так же стартап код (он необходим для запуска компилятора)
    Небольшую библиотечку API функций menuet.h--
    Библиотечку MeStdOut.h--
    (вывод ноль терминированных строк с форматированием 0dh 0ah)
    Прототип приложения MeFar - mefar.com (для запуска обрубите расширение файла)
    Исходники MeFar - mefar.c--, fat.h--

      Надеюсь Вы оцените всю мощь языка и компилятора, сайт которого находится по адресу www.sheker.narod.ru

Искренне Ваш, Алексей Сугоняев.
Email: alexey_s@ezmail.ru
Наверх / Up mailto:Webmaster
Hosted by uCoz