MeOs или еще одна "История игрушки"...

Mr.Clumsy (x25zine#04, March 2004)

Перевод на русский язык - Сергей Кузьмин (http://coolthemes.narod.ru), 11 января 2007 года
Ссылка на сайт http://coolthemes.narod.ru обязательна при копировании статьи!

Представляет интерес вторая часть статьи, где описано программирование сетевых программ.

Сначала я планировал сделать подробный обзор этой ОС, но поскольку сейчас информации об этой ОС уже достаточно много, то я ограничусь кратким описанием.

История MeOS уходит в далекий 2000-й год, когда идея о создании собственной ОС пришла в голову и была реализована руками некоего финского студента Ville Turjanmaa. MenuetOS (в дальнейшем MeOS...) была полностью написана на 32-битном ассемблере, она работает в защищенном режиме, имеет хорошо проработанный и довольно простой API графических программ (MFC нервно курит в сторонке(*замена - в оригинале применено нецензурное слово)), поддерживает VESA v.1.0 и v.2.0. Ядро уже имеет драйверы ethernet-карт(в основном для Realtek), мыши, звука и т.п. ... другими словами MeOS имеет достаточную поддержку для разработки программм. Она чертовски маленькая и вместе с большинством программ для неё может поместиться на одной 3.5-й дюймовой дискете. Несмотря на то, что ОС написана на асме, можно писать программы и на других языках программирования.

Основная файловая система для MeOS - это FAT32. Минимальный набор разработчикаt: текстовый редактор TinyPad и FASM - Flat Assembler [3].
Этого достаточно для создания вполне продвинутых программ.

Работа программ основана на событиях, т.е. на схеме:

1) ожидание события;
2) чтение типа события;
3) реагирование на него (или нереагирование).

Всё довольно просто. Обычная программа должна иметь обработчики трех базовых событий: перерисовки окна, нажатия на клавиатуру, нажатие на кнопки самого приложения.
Т.е. структура простейшего приложения:

схема

Необходимость обработать коды клавиатуры возникает, когда пользователь нажимает на клавиатуру, а обрабатывать нажатые кнопки требуется, если пользователь нажимает на кнопки в окне (самая простая реакция - завершение программы).

Системные вызовы в MeOS реализованы через прерывание 0x40. Меня тошнит от примеров типа "Hello world", поэтому я начал с портирования моей программы "3D stars", написанной давным-давно для MS-DOS. Это было проще и намного более интересно :).

В принципе, нет ничего сложного в программировании для MeOS, особенно для тех, кто имел опыт программирования для MS-DOS и любит ОСи на асме. Для любителей C++ и прочих языков высокого уровня это будет немного сложно (только на первых порах), но кто ищет легких путей 8).

Во время первого знакомства с MeOS, я удивлялся тому, что программы типа FASM, TinyPad и остальных, выглядят странно ;), если попробовать изменить размер их окна - развернуть на весь экран. Этих глюки не были критическими, но оставляли плохое впечатление. Кнопка "Закрыть", находящаяся в верхнем правом углу, оставалась на том же расстоянии от верхнего левого угла, что и до развертывания. Это выглядело хреново, если начальная ширина окна была 300 пикселей и после резвертки кнопка "закрыть" оказывалась в середине заголовка окна. Это меня раздражало и я исправил это.

Вот пример перерисовки кнопки "закрыть" из стандартных программ MeOS:

 ; CLOSE BUTTON 
mov eax,8 ; функция 8 : описать и нарисовать кнопку
mov ebx,(300-19)*65536+12 ; [x start] *65536 + [x size]
mov ecx,5*65536+12 ; [y start] *65536 + [y size]
mov edx,1 ; идентификатор кнопки в программе
mov esi,0x6677cc ; цвет кнопки RRGGBB
int 0x40

Это кусок из example.asm (автор Ville). Как мы можем видеть, координата x кнопки постоянна - (300-19)=281 пиксель от начала окна. При измененении ширины с 300 до 600 кнопка "закрыть" будет находится на том же месте (281,5).

На самом деле, реализация нормального окна без описанных глюков в интерфейсе не является сложной задачей. Не знаю, почему авторы других программ не исправили этот дефект (* все новые программы сейчас используют окна типа 3 или 4, где это исправление реализовано на уровне ядра, а кнопки заголовка (в т.ч. закрытия) добавляются автоматически). Вероятно, из-за лени или потому, что example.asm не содержал его. Ладно, сначала надо определить ширину окна из информации о текущем процессе:

 get_process_info:
mov eax,9 ; получить информацию о процессе
mov ebx,PInfo ; указатель на буфер, где данные будут храниться
; (1024 байта)
mov ecx,-1 ; получить информацию о текущем процессе
int 0x40

Кстати, официальное описание этой функции содержит маленькую опечатку (* может опечатка до сих пор содержится там?). Найдите её сами. Имея информацию о процессе, мы можем сделать окно без описанных багов:

 draw_window:
mov eax,12 ; функция 12: означает, что будет рисоваться окно
mov ebx,1 ; 1, начало рисования
int 0x40

mov eax,0 ; функция 0 : define and draw the window
mov ebx,100*65536 ; [x start] * 65536
add ebx,[process_window_width] ; добавим ширину
mov ecx,100*65536 ; [y start] * 65536
add ecx,[process_window_height] ; добавим высоту
mov edx,0x02000000 ; определим цвет
mov esi,0x805080d0 ; области заголовка и
mov edi,0x005080d0 ; границ
int 0x40
; название программы запишем в области заголовка
mov eax,4 ; функция 4 : вывести текст в окно
mov ebx,8*65536+8 ; [x start] * 65536 + [y start]
mov ecx,0x00ddeeff ; шрифт 0 и цвет ( 0xF0RRGGBB )
mov edx,labelt ; адрес текста
mov esi,labellen-labelt ; длина текста
int 0x40
; кнопка "закрыть"
mov eax,8 ; функция 8: описать и нарисовать кнопку
mov ebx,[process_window_width] ; ширина
sub ebx,19 ; -19
shl ebx,16 ; * 65536
add ebx,12 ; + ширина кнопки
mov ecx,5*65536+12 ; [y start] *65536 + [y size]
mov edx,1 ; идентификатор кнопки
mov esi,0x6688dd ; цвет кнопки RRGGBB
int 0x40 ...

 ; Информация о процессе
PInfo:
processor_use:
dd 0
stack_pos:
dw 0
stack_value:
dd 0
process_name:
db 0,0,0,0,0,0,0,0,0,0,0,0
process_address:
dd 0
used_memory:
dd 0
process_id:
dd 0
process_x_coord:
dd 0
process_y_coord:
dd 0
process_window_width:
dd 320
process_window_height:
dd 240

Итак, мы имеем красивое окно с кнопкой "закрыть" в верхнем правом углу ;) исходник прилагается (coolapp.asm).

Теперь обратимся к сети. Документация говорит нам, что сетевой стек имеет:

IP уровень.
ICMP.
TCP уровень.
UDP уровень.

+ полные:

local loopback.
Realtek 8029 PCI ethernet interface.
Realtek 8139 PCI ethernet interface.
Intel i8255x PCI ethernet interface.
Dynamic ARP table.
звонилка PPP

В процессе разработки:

The IP layer process header options.
The IP layer support routing.
Packet fragmentation.

Взаимодействие между хостами в сети, работающими под упарвлением MeOS, реализовано через сокеты (как во многих других ОСях).

К статье прилагаются два файла: client.asm/server.asm

Сервер открывает сокет на порте 83,

        mov  eax,53            ; открыть сокет tcp
mov ebx,5 ;
mov ecx,[local_port] ; 83-й порт
mov edx,0 ; удаленный порт 0, потому что этот параметр нам не важен because it's not necessary for us
mov esi,0 ; удаленный ip-адрес тоже неважен
mov edi,0 ; режим: SOCKET_PASSIVE
int 0x40

слушает и пишет входные данные:

mov eax,53 ; опросить сокет
mov ebx,2
mov ecx,[socket]
int 0x40 ;
cmp eax,0 ; в EAX количество байтов в буфере сокета
je no_data
mov eax,53 ; прочесть данные из сокета
mov ebx,3
mov ecx,[socket]
int 0x40 ; в BL после этого байт данных
mov byte [text+ebp],bl

<...>

И т.д.... (смотри исходники).

Соответственно, клиент подключается к порту и посылает данные, которые набраны на клавиатуре. Приятно, что возможно пересылать информацию даже одним байтом (что и сделано в примере):

 key:                           ; нажата ли клавиатура?
mov eax,2 ; прочтем код клавиши
int 0x40
cmp al,0 ; если al = 0, то нажата
jne still ; в AH - код клавиши

<...>
mov eax,53 ; записать символ в сокет
mov ebx,7
mov ecx,[socket]
mov edx,1 ; количество байтов для записи
mov esi,text ; адрес данных
add esi,ebp
int 0x40

Приближаясь к концу этого краткого повествования, можно отметить, что хотя MeOS еще довольно сыра и далека по возможностям от современных ОС, но она имеет очень хорошее начало...

Ссылки:

[1] http://www.menuetos.org
[2] http://www.flatassembler.net
[3] http://www.menuet.narod.ru

Файлы к статье



Hosted by uCoz