Программирование на ассемблере под PocketPC — Архив WASM.RU

Все статьи

Программирование на ассемблере под 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» выглядит следующим образом:

;---------------------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-------------------------------------------------------------------------

Пробежимся по каждой строчке кода.

include	wince.inc

wince.inc – быстро слепленный файлик, пока что кроме определений для MessageBoxW ничего не содержит. Надеюсь, когда-нибудь в него добавятся новые строки... Кстати, наблюдательный читатель сразу обратит внимание на то, что численно все определения для WinCE совпадают с «настольными», однако их значительно меньше…

IMPORT	MessageBoxW
IMPORT	ExitThread

armasm не поддерживает директиву типа includelib, поэтому каждую импортируемую функцию нужно указывать вот таким вот образом.

EXPORT	start

Дело в том, что без функции WinMainCRTStartup (которая автоматически создается в С) для платформы WindowsCE link.exe не сможет создать exe-файл - не найдя этой функции в объектнике, созданном armasm-ом, он просто грязно выругается. Поэтому мало того, что метку точки входа необходимо указать в экспорте, так еще и в параметрах к link.exe об этом нужно явно сказать при помощи опции /entry. Помнится, ml.exeсам делал всю подобную грязную работу и автоматически «назначал» точкой входа метку, которая была указана после директивы END. armasm настолько сырой (и, складывается впечатление – никому не нужный), что подобных наворотов просто не поддерживает.

AREA		.text, CODE

Здесь все понятно – это начало сегмента кода (.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 даже не пахнет. Хорошо это или плохо – программисту на асме вообщем-то как то все равно :), места больше в два раза жрет только…

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 попытаемся рассмотреть более насущные проблемы – например, написание драйвера под эту замечательную ОС.

2002-2013 (c) wasm.ru