Статья объясняет идеологию мультисегментных приложений для PalmOS с использованием GCC.
В информатике существует малоизвестный термин ABI - Application Binary Interface. Этим термином называют набор особенностей компьютерной архитектуры, которые нужно учитывать при создании приложения. ABI может накладываться процессором: направление роста стека, размер элемента данных в стеке, порядок байт в слове итд. Также ABI может накладываться операционной системой. Тогда в ABI входит способ вызова системного API, специфика использования адресного пространства и прочие нюансы. Изменения, которые вносятся в GCC для компиляции под PalmOS, нужны именно для соответствия PalmOS ABI.
Что такое приложение с точки зрения PalmOS? Приложение - это база ресурсов. Четыре ресурса из этой базы используются для исполнения программы. Это ресурс 'code' #1, в котором собственно и хранится исполняемый код, который запускается с нулевого байта ресурса. Также из ресурса 'code' #0 берется размеры области глобальных данных. Из ресурса 'pref' #0 берется размер стека. И ресурс 'data' #0 используется для инициализации глобальных данных. Все! До всего остального содержимого базы приложения PalmOS дела нет. Подробности можно почитать здесь: http://www.linuxmafia.com/pub/palmos/development/prc-format.html
Такой способ позволяет запускать программы практически “на месте”, выделяя только память под стек и глобальные переменные.
Какие ограничения накладываются на простое односегментное приложение?
Что усложнится при попытке добавить новый сегмент?
Самая большая проблема - межсегментный вызов процедуры. В случае одного сегмента расстояние между процедурами постоянно и код вызова не меняется после компиляции. В случае межсегментного вызова ресурсы могут располагаться в произвольных участках памяти и смещение нужно корректировать.
Замечу, что в односегментном приложении также происходит коррекция области данных. В нижележащем примере значение переменной pfn будет скорректировано. Это возможно, поскольку сегмент данных находится в динамической памяти. Копировать же все сегменты в динамическую память для коррекции неразумно и расточительно.
void foo(void){ } void *pfn = foo;
Все (оба ) производители компиляторов для PalmOS предлагают свои поддержки мультисегментности.
Gcc предлагает следующий способ:
В чем ограничения такого метода:
Подробное описание мультисегментной архитектуры GCC здесь: http://prc-tools.sourceforge.net/doc/prc-tools_3.html
Существует альтернативный способ создания мультисегментных приложений с помощью утилиты multilink. Смотри описание здесь: http://www.djw.org/product/palm/multilink/
Multilink использует другую идею:
У этого решения есть один большой минус - невозможен доступ к константным данным из другого сегмента.