Программирование и портирование ПО в МенуетОС.

на главную
Первое что вам надо для энтого дела это - сама Менует ОС. Советую использовать Колибри (модификация программистов из СНГ), так как она развивается быстрее своего предка из Финляндии.
Сначала развею представления некоторых людей: программировать под МеОС можно не только с помощью fasm'а, есть несколько других языков и компиляторов, которые официально поддерживают Менует.
Перейдём непосредственно к теме.

1. Какие языки?
2. Что нужно для начала?
3. Структура программы
4. API функции
5. Пишем собственную программу
6. Портирование программ
7. Товары первой необходимости
8. Распространение программы

#1. Ассемблер, С--, С ... И это ещё не всё (может быть сейчас какой-нибудь новоиспечённый Столлмен пишет MeMACS). Асм (fasm) идёт в стандартной поставке МенуетОС, и это единственно полноценный компилятор, работающий под МеОС. Остальные работают под Windows в режиме кросскомпиляции. НО существуют MeOS Emul, эмулятор МеОС в Win, и MeOS Debug - отладчик (также для Win'а). В Windows вы можете использовать любые текстовые редакторы и т.д. и т.п., а Менует предоставит вам отличный редактор Tinypad + отличные средства отладки. Всё-таки программирование для МеOCи должно совершаться под него самого (исключение составляют С-- и С - компиляторы этих языков пока не портированы в МенуетОС). В этой статье будут рассматриваться ассемблер и С--.

#2. Нужно иметь представление, что такое программирование, если вы только узнали про асм, то иметь хорошую книгу по ассемблеру и нужно скачать 500 Кб дзенского счастья с русского офф. сайта (или с этого сайта, смотрите раздел Файлы).

#3. Программа в МеОС состоит из трёх частей:
Заголовок, обработчик событий, цикл прорисовки окна.
;Заголовок

use32 ;32-х битная программа
org 0x0
db 'MENUET01' ;8 байтовый идентификатор
dd 0x01 ;версия заголовка
dd START ;начало кода
dd I_END ;размер программы
dd 0x100000 ;память для программы
dd 0x7fff0 ;esp
dd 0x0 , 0x0 ;I_Param , I_Icon


;метка начала программы
START:
call draw_window ;вызываем цикл прорисовки окна

;обработчик событий

;цикл прорисовки окна (это не обязательная часть программы - программа может быть и без оконного интерфейса)
draw_window:

;метка конца программы
I_END:


#4. API функции вызываются аналогично функциям ОС Linux:

В регистр eax помещается номер функции, далее задаются параметры в 32-битных регистрах (есть функции и без параметров), далее вызывается прерывание 0x40.
Например:

mov eax,1 ;функция рисования точки в окне
mov ebx,50 ;координаты по оси x
mov ecx,75 ;координаты по оси y
mov edx,0x00ff0000 ;цвет точки в формате 0x0zRRGGBB, если z=0 - нормальный цвет,=1 - негатив.
int 0x40 ;вызов прерывания 0x40

#5. Чтобы написать свою программу достаточно добавить свой код к вышеописанной структуре, в любом месте между метками START: и I_END: , главное правильно организовать переходы между прорисовкой окна и вашим кодом, если у программы есть оконный интерфейс. Если нет, то дело пойдёт ещё быстрее. Вместо call draw_window, после метки START можно указать своё начало программы.
Советую для начала продумать алгоритм работы программы, так как сразу кодить без алгоритма никто не может (даже воины дзена). В программировании самое главное это умение составлять алгоритмы, а не умение кодить (хотя последнее - необходимое умение для программиста).

#6. Я не нашёл в интернете общей информации по портированию программ, поэтому выкладываю свои наработки в этой области. Первое что надо сделать - это убедиться, что программа распространяется с исходниками. Если софт проприетарный (aka коммерческий), то это будет не портирование, а reverse engineering и в данном руководстве он не рассматривается (хотя в последующих редакциях этого документа возможны изменения). Второе правильно прочитать код и выяснить чёткий алгоритм работы. Здесь подробнее. Вся соль портирования в том, что исходная программа может быть написана на бейсике, а в МеОС вы перенесёте её на ассемблере или C--. И третья стадия - собственно кодинг.

Пример портирования программы:

Для примера была взята программа на Visual Basic'е и была портирована в MeOC на языке С--. Первый был выбран из-за своей простоты и удаленности от низкого уровня программирования, второй - из-за легкости написания под него программ для MeOC.
Программа на VB предназначена для расчета сопротивления резистора, по цветным полосам, нанесенным на его корпус.
Читаем программу на бейсике:

На форме размещены GUI-компоненты, как показано на рисунке



Dim rez As Integer 'объявлены две переменные типа integer (целое число)
Dim st As Integer

Private Sub Command1_Click()     'обработчик нажатия кнопки Command1
Select Case st     'при её нажатии проверяется значение переменной st, это переменная - счетчик
Case 1:     'если значение 1, то значит определяется цвет первой полоски
rez = 0     'на корпусе сопротивления
st = st + 1
Label1.Caption = "Цвет второй полоски"
Case 2:     'если 2, то вторая
st = st + 1
Label1.Caption = "Цвет третьей полоски"
Case 3:     '3 - третьей
Label2.Caption = rez     'и после определения третьей полоски
Label3.Caption = "Ом"     'на форме появляется значение сопротивления в Ом,КОм,МОм или ГОм
rez = 0
st = 1
Label1.Caption = "Цвет первой полоски"
End Select
End Sub

'остальные кнопки обрабатываются аналогично

Private Sub Command10_Click()
Select Case st
Case 1:
rez = 9
st = st + 1
Label1.Caption = "Цвет второй полоски"
Case 2:
rez = rez * 10 + 9
st = st + 1
Label1.Caption = "Цвет третьей полоски"
Case 3:
Label2.Caption = rez
Label3.Caption = "ГОм"
rez = 0
st = 1
Label1.Caption = "Цвет первой полоски"
End Select
End Sub

Private Sub Command11_Click()     '--------------------------------------------
Label6.Caption = "10%"
End Sub

Private Sub Command12_Click()
Label6.Caption = "5%"     'Кнопки определения точности сопротивления
End Sub

Private Sub Command13_Click()
Label6.Caption = "20%"
End Sub     '--------------------------------------------

Private Sub Command2_Click()
Select Case st
Case 1:
rez = 1
st = st + 1
Label1.Caption = "Цвет второй полоски"
Case 2:
rez = rez * 10 + 1
st = st + 1
Label1.Caption = "Цвет третьей полоски"
Case 3:
rez = rez * 10
Label2.Caption = rez
Label3.Caption = "Ом"
rez = 0
st = 1
Label1.Caption = "Цвет первой полоски"
End Select
End Sub

Private Sub Command3_Click()
Select Case st
Case 1:
rez = 2
st = st + 1
Label1.Caption = "Цвет второй полоски"
Case 2:
rez = rez * 10 + 2
st = st + 1
Label1.Caption = "Цвет третьей полоски"
Case 3:
rez = rez * 100
Label2.Caption = rez
Label3.Caption = "Ом"
rez = 0
st = 1
Label1.Caption = "Цвет первой полоски"
End Select
End Sub

Private Sub Command4_Click()
Select Case st
Case 1:
rez = 3
st = st + 1
Label1.Caption = "Цвет второй полоски"
Case 2:
rez = rez * 10 + 3
st = st + 1
Label1.Caption = "Цвет третьей полоски"
Case 3:
Label2.Caption = rez
Label3.Caption = "КОм"
rez = 0
st = 1
Label1.Caption = "Цвет первой полоски"
End Select
End Sub

Private Sub Command5_Click()
Select Case st
Case 1:
rez = 4
st = st + 1
Label1.Caption = "Цвет второй полоски"
Case 2:
rez = rez * 10 + 4
st = st + 1
Label1.Caption = "Цвет третьей полоски"
Case 3:
rez = rez * 10
Label2.Caption = rez
Label3.Caption = "КОм"
rez = 0
st = 1
Label1.Caption = "Цвет первой полоски"
End Select
End Sub

Private Sub Command6_Click()
Select Case st
Case 1:
rez = 5
st = st + 1
Label1.Caption = "Цвет второй полоски"
Case 2:
rez = rez * 10 + 5
st = st + 1
Label1.Caption = "Цвет третьей полоски"
Case 3:
rez = rez * 100
Label2.Caption = rez
Label3.Caption = "КОм"
rez = 0
st = 1
Label1.Caption = "Цвет первой полоски"
End Select
End Sub

Private Sub Command7_Click()
Select Case st
Case 1:
rez = 6
st = st + 1
Label1.Caption = "Цвет второй полоски"
Case 2:
rez = rez * 10 + 6
st = st + 1
Label1.Caption = "Цвет третьей полоски"
Case 3:
Label2.Caption = rez
Label3.Caption = "МОм"
rez = 0
st = 1
Label1.Caption = "Цвет первой полоски"
End Select
End Sub

Private Sub Command8_Click()
Select Case st
Case 1:
rez = 7
st = st + 1
Label1.Caption = "Цвет второй полоски"
Case 2:
rez = rez * 10 + 7
st = st + 1
Label1.Caption = "Цвет третьей полоски"
Case 3:
rez = rez * 10
Label2.Caption = rez
Label3.Caption = "МОм"
rez = 0
st = 1
Label1.Caption = "Цвет первой полоски"
End Select
End Sub

Private Sub Command9_Click()
Select Case st
Case 1:
rez = 8
st = st + 1
Label1.Caption = "Цвет второй полоски"
Case 2:
rez = rez * 10 + 8
st = st + 1
Label1.Caption = "Цвет третьей полоски"
Case 3:
rez = rez * 100
Label2.Caption = rez
Label3.Caption = "МОм"
rez = 0
st = 1
Label1.Caption = "Цвет первой полоски"
End Select
End Sub

Private Sub Form_Load()     'при загрузке формы на ней появляется
Label1.Caption = "Цвет первой полоски"     'надпись "Цвет первой полоски"
st = 1     'и значение переменной-счётчика st
End Sub     'устанавливается равным 1

Алгоритм таков:
1. Определяем цвет первой полоски - узнаём первую цифру
2. Определяем цвет второй - узнаём вторую цифру
3. Определяем цвет третьей полоски - количество нулей, которые добавляются к первым двум цифрам.
Полученное число является значением сопротивления.
Цветовая таблица:
чёрный - 0
коричневый - 1
красный - 2
оранжевый - 3
жёлтый - 4
зелёный - 5
синий - 6
сиреневый - 7
серый - 8
белый - 9
4. Четвёртая полоска - точность сопротивления
а)золотой - точность 5%
б)серебренный - 10%
в)полоска отсутствует - 20%


Теперь портируем на C--:

#include "msys.h--"
#codesize     //оптимизация программы по размеру

int rez;     //объявляем 6 переменных
int rez2;
int rez3;
int ste=1;     //переменная - счетчик
dword mn;     //строковые переменные
dword tochn;

draw_window(){ //цикл прорисовки окна
sys_window_redraw(1);
sys_draw_window(100*65536+207,100*65536+237,0x03c0c0c0,0x00000000,0x00000000);
sys_write_text(8*65536+8,0x10ffffff, "Омметр v1.0", 11);

sys_draw_button(8*65536+33,32*65536+33,2,0x00c0c0c0);
sys_write_text(15*65536+43,0x10000000, "чёр", 3);

sys_draw_button(48*65536+33,32*65536+33,3,0x00c0c0c0);
sys_write_text(55*65536+43,0x10000000, "кор", 3);

sys_draw_button(88*65536+33,32*65536+33,4,0x00c0c0c0);
sys_write_text(100*65536+43,0x10000000, "кр", 2);

sys_draw_button(128*65536+33,32*65536+33,5,0x00c0c0c0);
sys_write_text(130*65536+43,0x10000000, "оран",4);

sys_draw_button(168*65536+33,32*65536+33,6,0x00c0c0c0);
sys_write_text(175*65536+43,0x10000000, "жел",3);

sys_draw_button(8*65536+33,72*65536+33,7,0x00c0c0c0);
sys_write_text(15*65536+83,0x10000000, "зел",3);

sys_draw_button(48*65536+33,72*65536+33,8,0x00c0c0c0);
sys_write_text(55*65536+83,0x10000000, "син",3);

sys_draw_button(88*65536+33,72*65536+33,9,0x00c0c0c0);
sys_write_text(96*65536+83,0x10000000, "сир",3);

sys_draw_button(128*65536+33,72*65536+33,10,0x00c0c0c0);
sys_write_text(133*65536+83,0x10000000, "сер",3);

sys_draw_button(168*65536+33,72*65536+33,11,0x00c0c0c0);
sys_write_text(175*65536+83,0x10000000, "бел",3);

sys_write_number(4*65536,rez3,24*65536+120,0x0);
sys_write_text(140*65536+120,0x00000000, mn, 3);
rez=0;
ste=1;

sys_draw_button(24*65536+73,168*65536+17,12,0x00c0c0c0);
sys_draw_button(104*65536+81,168*65536+17,13,0x00c0c0c0);
sys_draw_button(24*65536+161,192*65536+17,14,0x00c0c0c0);
sys_write_text(75*65536+197,0x00000000, "полоски нет", 11);
sys_write_text(120*65536+173,0x00000000, "золотой", 7);
sys_write_text(30*65536+173,0x00000000, "серебряный", 10);
sys_write_text(24*65536+144,0x00000000, "Цвет четвёртой полоски", 22);
sys_write_text(8*65536+216,0x00000000, "Точность сопротивления", 22);
sys_write_text(152*65536+216,0x00000000, tochn, 3);
sys_window_redraw(2);
}

Вот что получается после функции прорисовки окна



очень похоже на VB.

void button_pressed(){     //обработка события нажатия кнопки
sys_get_button_id();

switch(EAX){
case 1:
sys_exit_process();     //если id=1 то значит нажата кнопка закрытия окна - завершение работы процесса

case 2:     //далее точно также как на VB, только с несущественными изменениями
switch(ste){     //вызванными различиями в структуре программ
case 1:
rez=0;
ste++;
break;
case 2:
ste++;
break;
case 3:
mn="Ом";
rez3=rez;
draw_window();
}
break;
case 3:
rez2=rez;
switch(ste){
case 1:
rez=1;
ste++;
break;
case 2:
rez=rez2*10+1;
ste++;
break;
case 3:
mn="Ом";
rez=rez2*10;
rez3=rez;
draw_window();
}
break;

case 4:
rez2=rez;
switch(ste){
case 1:
rez=2;
ste++;
break;
case 2:
rez=rez2*10+2;
ste++;
break;
case 3:
mn="Ом";
rez=rez2*100;
rez3=rez;
draw_window();
}
break;

case 5:
rez2=rez;
switch(ste){
case 1:
rez=3;
ste++;
break;
case 2:
rez=rez2*10+3;
ste++;
break;
case 3:
mn="КОм";
rez3=rez;
draw_window();
}
break;

case 6:
rez2=rez;
switch(ste){
case 1:
rez=4;
ste++;
break;
case 2:
rez=rez2*10+4;
ste++;
break;
case 3:
mn="КОм";
rez=rez2*10;
rez3=rez;
draw_window();
}
break;
case 7:
rez2=rez;
switch(ste){
case 1:
rez=5;
ste++;
break;
case 2:
rez=rez2*10+5;
ste++;
break;
case 3:
mn="КОм";
rez=rez2*100;
rez3=rez;
draw_window();
}
break;
case 8:
rez2=rez;
switch(ste){
case 1:
rez=6;
ste++;
break;
case 2:
rez=rez2*10+6;
ste++;
break;
case 3:
mn="МОм";
rez3=rez;
draw_window();
}
break;
case 9:
rez2=rez;
switch(ste){
case 1:
rez=7;
ste++;
break;
case 2:
rez=rez2*10+7;
ste++;
break;
case 3:
mn="МОм";
rez=rez2*10;
rez3=rez;
draw_window();
}
break;
case 10:
rez2=rez;
switch(ste){
case 1:
rez=8;
ste++;
break;
case 2:
rez=rez2*10+8;
ste++;
break;
case 3:
mn="МОм";
rez=rez2*100;
rez3=rez;
draw_window();
}
break;
case 11:
rez2=rez;
switch(ste){
case 1:
rez=9;
ste++;
break;
case 2:
rez=rez2*10+9;
ste++;
break;
case 3:
mn="ГОм";
rez3=rez;
draw_window();
}
break;

case 12:
tochn="10%";
break;
case 13:
tochn="5%";
break;
case 14:
tochn="20%";
break;
}
}

void main(){     //работа программы начинается с функции main()
mn="Ом";
tochn="0%";
draw_window();
while(){     //обработка событий
sys_wait_event();
switch(EAX){
case 1:     //sys_wait_event() возвращает номер события в регистре EAX
draw_window();     //если EAX=1, то значит событие прорисовки окна
case 3:
button_pressed();     //если EAX=3 - нажата кнопка
}
}
}


Вот собственно и всё. Данный пример не претендует на полноту описания техники портирования, но даёт понятие, что это такое - портирование. Программы также не оптимизированы, но отлажены и работают.

#7. Сейчас МеОС нуждается в следующем софте:
Компиляторы языков высокого уровня
MP3 и видео плейеры
Офисный пакет программ
Веб-браузер и почтовый клиент
Графические редакторы
Игровой 3D-движок
(везде ставить пометку "удобные для пользования")

#8. Если вы пишете программу для МенуетОС, то значит вы уже хакер и вы хотите работать на благо людей. Вы готовы распространять свою программу с её исходными текстами. Значит, вам нужна лицензия. Ответ однозначен GNU GPL - Генеральная Общедоступная Лицензия ГНУ. В ней описаны все правила использования и распространения программы с открытыми исходными кодами. И можно смело использовать вторую версию сего документа (кстати, скоро выйдет третья версия лицензии). Найти её можно на http://www.gnu.org/.

Umarov German (c)2005
Файлы упоминаемые в статье port_vb-c.7z
на главную
Сайт создан в системе uCoz