Программирование на ассемблере под PocketPC — Архив WASM.RU
Для начала разберемся с основными понятиями и определениями: PocketPC и WindowsCE – это (с недавних пор) одна и та же операционная система реального времени (real-timeOS); предназначена она для т.н. встраиваемых (embedded) систем (КПК, банкоматы, бортовые компьютеры в автомобилях и т.п.).
Одной из главных характеристик систем реального времени является стабильность. Не беспокойтесь – Microsoft не отступила от своих традиций: WinCE подвисает довольно часто, причем даже от вполне безобидных ошибок в прикладных программах. Поэтому прежде чем запускать программу в КПК ее нужно тщательно обследовать на эмуляторе.
Еще одно преймущество WindowsCE– компактность. В ней реализовано в десять раз меньше API-функций, чем, к примеру, в WinNT. Для сравнения – главная системная библиотека в WindowsXP (kernel32.dll) весит 914 Кб, тогда как аналогичная библиотека из WindowsCE (coredll.dll) – всего 509 Кб. О чем говорят эти цифры? Да ни о чем J. Просто из coredll.dll выкинули много старых, ненужных для совместимости с Win9xфункций. Правда, добавили несколько новых. Вообще, некорректно сравнивать настольные ОС со встроенными, поэтому оставим эту тему.
Принцип модульности – вот основное преимущество этой, да и всех других встраиваемых ОС: WinCE состоит из множества модулей (около 220 «exe» и «dll» файлов, причем каждый модуль состоит из нескольких компонент («lib»), что делает эту ОС совсем пластилиновой), которые можно легко отключать и включать, т.е. WinCE – это конструктор, который может собрать любой под свои конкретные нужды с помощью PlatformBuilder-а, и если, к примеру, вашему холодильнику не нужны сокеты – вы просто не включаете их в конечный build. Что-то подобное можно наблюдать при инсталляции настольных версий Win – нам дают возможность избавиться от некоторых компонент, однако ядро и системные библиотеки остаются неизменными. Здесь же можно менять абсолютно все, вплоть до ядра. Таким образом, достигается минимальный размер и максимальное быстродействие. В принципе, по заверениям разработчиков, всю WinCE можно уместить в 400 Кб и она будет работать с 32 Кб оперативной памяти. С графическим интерфейсом (модуль GWES) она потянет уже на 4 Мб.
WinCE поддерживает множество процессоров (ARM, MIPS, x86), полный список можно посмотреть здесь:
http://www.microsoft.com/windowsce/Embedded/resources/processors.asp
Архитектура WinCE не является темой данной статьи, об этом вы можете почитать в MSDN. Поэтому перейдем непосредственно к главному.
Что необходимо для того, чтобы написать простейшую программку на асме для WinCE? Прежде всего – это … (нет, не больная психика, хотя не без этого) ассемблер для нужного проца, линкер и само устройство (или его эмулятор). Мой КПК Toshibae755 стоит на IntelPXA255 проце (который, в свою очередь, стоит на архитектуре ARM 5TE) . Поэтому в качестве ассемблера я использовал MSARMASM, который идет вместе с eVC (и который вы можете скачать по ссылке в конце статьи). Линкер – самый обычный MSlink.
Следует отметить, что ARMASM снабдили какой-то кой-как, на скору рученьку слепленной документацией (кое-что есть в MSDN, кое что есть в документации от eVC), хотя, очень возможно, что он и не содержит никаких неописанных возможностей.
В Интернете существует достаточное количество качественных ARM-ассемблеров, однако ни один из известных мне не знает ни про COFF, ни про PE (а именно он, кстати, и используется в WinCE).
Сразу признаюсь – на то чтобы простейшее «HelloWorld» приложение скомпилировалось и нормально запустилось я убил целый день. Однако результат оправдывает затраченные усилия – в итоге получился в три раза меньший по сравнению с С-шным exe-шник, а критерий размера ох как критичен для emb-систем, что бы там ни говорили настольные сотоварищи.
Предполагается, что вы более-менее знакомы с программированием под Win32 на ассемблере и с ARM-овским асмом.
Код стандартного «HelloWorld» выглядит следующим образом:
Код (Text):
;---------------------cut here------------------------------------------------------------------------- include wince.inc IMPORT MessageBoxW IMPORT ExitThread EXPORT start AREA .text, CODE start eor R0, R0, R0 adr R1, mestext adr R2, mestit mov R3, #MB_OK bl MessageBoxW eor R0, R0, R0 bl ExitThread mestext dcb "H",0,"e",0,"l",0,"l",0,"o",0," ",0,"w",0,"o",0,"r",0,"l",0,"d",0,0,0 mestit dcb "A",0,"S",0,"M",0,0,0 END ;---------------------cut here-------------------------------------------------------------------------Пробежимся по каждой строчке кода.
Код (Text):
<strong>include wince.inc</strong>wince.inc – быстро слепленный файлик, пока что кроме определений для MessageBoxW ничего не содержит. Надеюсь, когда-нибудь в него добавятся новые строки... Кстати, наблюдательный читатель сразу обратит внимание на то, что численно все определения для WinCE совпадают с «настольными», однако их значительно меньше…
Код (Text):
IMPORT MessageBoxW IMPORT ExitThreadarmasm не поддерживает директиву типа includelib, поэтому каждую импортируемую функцию нужно указывать вот таким вот образом.
Код (Text):
EXPORT startДело в том, что без функции WinMainCRTStartup (которая автоматически создается в С) для платформы WindowsCE link.exe не сможет создать exe-файл - не найдя этой функции в объектнике, созданном armasm-ом, он просто грязно выругается. Поэтому мало того, что метку точки входа необходимо указать в экспорте, так еще и в параметрах к link.exe об этом нужно явно сказать при помощи опции /entry. Помнится, ml.exeсам делал всю подобную грязную работу и автоматически «назначал» точкой входа метку, которая была указана после директивы END. armasm настолько сырой (и, складывается впечатление – никому не нужный), что подобных наворотов просто не поддерживает.
Код (Text):
AREA .text, CODEЗдесь все понятно – это начало сегмента кода (.text – это имя, и может быть любым)
Код (Text):
eor R0, R0, R0 adr R1, mestext adr R2, mestit mov R3, #MB_OK bl MessageBoxWВ отличие от x86 (где параметры передаются в стеке) здесь параметры в функции передаются в регистрах (первый – в R0, второй – в R1 и т.д.). Результат возвращается в R0 (аналог EAX на x86). Здесь происходит вызов функции MessageBoxW – на экран выводится окошко с текстом. Почему W? Дело в том, что WinCE поддерживает только Unicode. MessageBoxA в coredll даже не пахнет. Хорошо это или плохо – программисту на асме вообщем-то как то все равно , места больше в два раза жрет только…
Код (Text):
eor R0, R0, R0 bl ExitThreadПочему ExitThread, а не ExitProcess? Все достаточно загадочно – дело в том, что coredll вообще не экспортирует ExitProcess, хотя в MSDN-е написано обратное. Близкий родственник – TerminateProcess есть, однако применять его крайне не рекомендуется. Еще больше смутила следующая строка, обнаруженная в одном из инклюдов к eVC:
#define ExitProcess(code) TerminateProcess (GetCurrentProcess (), (code))
Если у кого есть мысли по поводу того, зачем было избавляться от ExitProcess – прошу в комментарии. ExitThread из основного потока аналогичен ExitProcess, именно им я воспользовался (все таки, куда делся ExitProcess?)
С mestext и mestit все и так понятно – такая убогость возникла из-за того, что dcw для ASCII-символов в armasm-е не поддерживается, а писать макрос как-то не было времени.
Несколько слов по поводу компиляции:
armasm.exe -32 -cpu xscale entry.s
-32 – генерить 32-битный код.
xscale – мой проц
link.exe coredll.lib /nologo /entry:"start" /subsystem:windowsce /machine:arm "entry.obj"
/machine:arm – без этого параметра PocketPC ругается и кричит, что формат файла неправильный. На самом деле все что он делает – меняет байт Machine в заголовке PE с Thumbна ARM, хотя почему там оказался 16-битный ARM вместо 32-х битного? Это значит лишь то, что параметр -32 в armasm просто не работает… L
Помните, в начале статьи я упоминал о глюкавости WinCE? Можете сами поэкспериментировать. Задайте, например, выравнивание секций на 4 байта. В итоге вы получите еще в три раза меньший файл… (716 байт) и безумное поведение WinCE при попытке его запустить.
Все необходимые файлы (кроме link.exe) можно скачать тут.
Это все. В следующей статье по WinCE попытаемся рассмотреть более насущные проблемы – например, написание драйвера под эту замечательную ОС.
© Broken Sword
Программирование на ассемблере под PocketPC
Дата публикации 7 июл 2004