-<ow:wiki version="0.91" encoding="windows-1251" mode="diff">
 <ow:useragent>CCBot/2.0 (https://commoncrawl.org/faq/)</ow:useragent>
 <ow:location>http://wiki.palmoid.com/</ow:location>
 <ow:scriptname>ow.asp</ow:scriptname>
 <ow:imagepath>ow/images</ow:imagepath>
 <ow:iconpath>ow/images/icons</ow:iconpath>
 <ow:about>http://wiki.palmoid.com/ow.asp?p=PalmMultiSegment&a=diff&revision=&xml=1</ow:about>
 <ow:title>O p e n W i k i</ow:title>
 <ow:frontpage name="PalmNotes" href="ow.asp?PalmNotes">Palm Notes</ow:frontpage>
-<ow:userpreferences>
 <ow:cols>55</ow:cols>
 <ow:rows>25</ow:rows>
 <ow:username />
-<ow:bookmarks>
 <ow:link name="PalmNotes" href="ow.asp?PalmNotes">Palm Notes</ow:link>
 <ow:link name="RecentChanges" href="ow.asp?RecentChanges">Recent Changes</ow:link>
 <ow:link name="TitleIndex" href="ow.asp?TitleIndex">Title Index</ow:link>
 <ow:link name="UserPreferences" href="ow.asp?UserPreferences">User Preferences</ow:link>
 <ow:link name="RandomPage" href="ow.asp?RandomPage">Random Page</ow:link>
 <ow:link name="Help" href="ow.asp?Help">Help</ow:link>
 </ow:bookmarks>
 <ow:prettywikilinks />
 <ow:opennew />
 <ow:emoticons />
 <ow:bookmarksontop />
 <ow:editlinkontop />
 <ow:trailontop />
 </ow:userpreferences>
-<ow:trail>
 <ow:link name="PalmMultiSegment" href="ow.asp?PalmMultiSegment">Palm Multi Segment</ow:link>
 </ow:trail>
-<ow:diff type="major" from="5" to="6">
 Статья объясняет идеологию мультисегментных приложений для 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 Такой способ позволяет запускать программы практически "на месте", выделяя только память под стек и глобальные переменные. Какие ограничения накладываются на простое односегментное приложение? * Размер ресурса 'code' #0 ограничен 64К. Это ограничение было у PalmOS включая версию 4 и у Хотсинка до версии 5 включительно. Условное ограничение сегмента GCC в 32К лечится заменой скрипта для линкера на text_64k. * Ограничение смещения у команды вызова процедуры в 32К. То есть, если сегмент больше 32К, то функция из начала не может вызвать функцию в конце сегмента. Это можно обойти путем перемещения вызываемых функций "поближе" к вызываемым или созданием
 <strike class="diff"> прокси-функций</strike>
 <u class="diff"> функций-заглушек</u>
  в середине сегмента. * Ограничение размера глобальных данных программы. Общий объем глобальных данных (в сумме инициализированных и неинициализированных) должен укладываться в 64К. Замечу, что константные инициализированные данные помещаются в сегмент кода. Что усложнится при попытке добавить новый сегмент? Самая большая проблема - межсегментный вызов процедуры. В случае одного сегмента расстояние между процедурами постоянно и код вызова не меняется после компиляции. В случае межсегментного вызова ресурсы могут располагаться в произвольных участках памяти и смещение нужно корректировать. Замечу, что в односегментном приложении также происходит коррекция области данных. В нижележащем примере значение переменной pfn будет скорректировано. Это возможно, поскольку сегмент данных находится в динамической памяти. Копировать же все сегменты в динамическую память для коррекции неразумно и расточительно. <code> void foo(void){ } void *pfn = foo; </code> Все (оба ;-) ) производители компиляторов для PalmOS предлагают свои поддержки мультисегментности. Gcc предлагает следующий способ: * Всем функциям приписывается атрибут с именем сегмента. Функции помещаются в соответствующие
 <strike class="diff"> сегменты.</strike>
 <u class="diff"> сегменты единственного получаемого ELF-файла.</u>
  * В области глобальных переменных хранятся адреса всех сегментов * При вызове функции из другого семента происходит сложение смещения функции от начала сегмента к адресу сегмента из глобальной памяти В чем ограничения такого метода: * Использование глобальных данных. Это обозначает, что при вызове программы без глобальных переменных, вызов функций из других сегментов попросту невозможен. При попытке вызвать произойдет обращение к несуществующей области глобалных данных и Fatal Alert неизбежен. * Этот способ никак не расширяет область глобальных данных. * Проблемы с доступом к константным данным. Константные данные могут оказаться в другом сегменте и тебовать наличия глобальных данных. * Неявные функции и методы класса. C++ богат на неявную генерацию неявного кода. Следует контролировать куда будет помещен код темплейтов и не инлайновых инлайнов.
 <u class="diff">Подробное описание мультисегментной архитектуры GCC здесь: http://prc-tools.sourceforge.net/doc/prc-tools_3.html Существует альтернативный способ создания мультисегментных приложений с помощью утилиты multilink. Смотри описание здесь: http://www.djw.org/product/palm/multilink/ Multilink использует другую идею: * Исходные файлы компилируются как обычно. Не нужно указывать сегменты в исходном коде * Утилита получает на вход объектные файлы и необязательный список разбиения функций по сегментам. * Утилита разбивает все функции по сегментам по списку и добивает оставшиеся до указанного размера сегментов. * Если функция foo из сегмента segA вызывает bar из сегмента srgB, то в segA добавляется заглушка для bar, вызывающая bar. * Для вычисления адреса bar используются данные, которые хранятся в feature memory. Тем самым наличие глобальных данных необязательно. * Полученные сегменты добавляются в программу. У этого решения есть один большой минус - невозможен доступ к константным данным из другого сегмента. </u>
 </ow:diff>
-<ow:page name="PalmMultiSegment" changes="6" lastminor="6" lastmajor="6">
 <ow:link name="PalmMultiSegment" href="ow.asp?PalmMultiSegment" date="2003-12-02T20:49:09+01:00">Palm Multi Segment</ow:link>
-<ow:change revision="6" status="new" minor="false">
 <ow:by name="172.16.243.xxx" />
 <ow:date>2003-12-02T20:49:09+01:00</ow:date>
 </ow:change>
-<ow:body>
 Статья объясняет идеологию мультисегментных приложений для
 <ow:link name="PalmOS" href="ow.asp?PalmOS" date="2003-05-13T18:59:32+01:00">Palm OS</ow:link>
  с использованием GCC.
 <p />
  В информатике существует малоизвестный термин ABI - Application Binary Interface. Этим термином называют набор особенностей компьютерной архитектуры, которые нужно учитывать при создании приложения. ABI может накладываться процессором: направление роста стека, размер элемента данных в стеке, порядок байт в слове итд. Также ABI может накладываться операционной системой. Тогда в ABI входит способ вызова системного API, специфика использования адресного пространства и прочие нюансы. Изменения, которые вносятся в GCC для компиляции под
 <ow:link name="PalmOS" href="ow.asp?PalmOS" date="2003-05-13T18:59:32+01:00">Palm OS</ow:link>
 , нужны именно для соответствия
 <ow:link name="PalmOS" href="ow.asp?PalmOS" date="2003-05-13T18:59:32+01:00">Palm OS</ow:link>
  ABI.
 <p />
  Что такое приложение с точки зрения
 <ow:link name="PalmOS" href="ow.asp?PalmOS" date="2003-05-13T18:59:32+01:00">Palm OS</ow:link>
 ? Приложение - это база ресурсов. Четыре ресурса из этой базы используются для исполнения программы. Это ресурс 'code' #1, в котором собственно и хранится исполняемый код, который запускается с нулевого байта ресурса. Также из ресурса 'code' #0 берется размеры области глобальных данных. Из ресурса 'pref' #0 берется размер стека. И ресурс 'data' #0 используется для инициализации глобальных данных. Все! До всего остального содержимого базы приложения
 <ow:link name="PalmOS" href="ow.asp?PalmOS" date="2003-05-13T18:59:32+01:00">Palm OS</ow:link>
  дела нет. Подробности можно почитать здесь:
 <a href="http://www.linuxmafia.com/pub/palmos/development/prc-format.html" class="external" target="_blank">http://www.linuxmafia.com/pub/palmos/development/prc-format.html</a>
 <p />
  Такой способ позволяет запускать программы практически "на месте", выделяя только память под стек и глобальные переменные.
 <p />
  Какие ограничения накладываются на простое односегментное приложение?
-<ul>
-<li>
 Размер ресурса 'code' #0 ограничен 64К. Это ограничение было у
 <ow:link name="PalmOS" href="ow.asp?PalmOS" date="2003-05-13T18:59:32+01:00">Palm OS</ow:link>
  включая версию 4 и у Хотсинка до версии 5 включительно. Условное ограничение сегмента GCC в 32К лечится заменой скрипта для линкера на text_64k.
 </li>
 <li>Ограничение смещения у команды вызова процедуры в 32К. То есть, если сегмент больше 32К, то функция из начала не может вызвать функцию в конце сегмента. Это можно обойти путем перемещения вызываемых функций "поближе" к вызываемым или созданием функций-заглушек в середине сегмента.</li>
 <li>Ограничение размера глобальных данных программы. Общий объем глобальных данных (в сумме инициализированных и неинициализированных) должен укладываться в 64К. Замечу, что константные инициализированные данные помещаются в сегмент кода.</li>
 </ul>
 <p />
  Что усложнится при попытке добавить новый сегмент?
 <p />
 <p />
  Самая большая проблема - межсегментный вызов процедуры. В случае одного сегмента расстояние между процедурами постоянно и код вызова не меняется после компиляции. В случае межсегментного вызова ресурсы могут располагаться в произвольных участках памяти и смещение нужно корректировать.
 <p />
  Замечу, что в односегментном приложении также происходит коррекция области данных. В нижележащем примере значение переменной pfn будет скорректировано. Это возможно, поскольку сегмент данных находится в динамической памяти. Копировать же все сегменты в динамическую память для коррекции неразумно и расточительно.
 <pre class="code"> void foo(void){ } void *pfn = foo; </pre>
 <p />
  Все (оба
 <img src="ow/images/icons/emoticon-wink.gif" width="14" height="12" alt="" />
  ) производители компиляторов для
 <ow:link name="PalmOS" href="ow.asp?PalmOS" date="2003-05-13T18:59:32+01:00">Palm OS</ow:link>
  предлагают свои поддержки мультисегментности.
 <p />
  Gcc предлагает следующий способ:
-<ul>
 <li>Всем функциям приписывается атрибут с именем сегмента. Функции помещаются в соответствующие сегменты единственного получаемого ELF-файла.</li>
 <li>В области глобальных переменных хранятся адреса всех сегментов</li>
 <li>При вызове функции из другого семента происходит сложение смещения функции от начала сегмента к адресу сегмента из глобальной памяти</li>
 </ul>
 <p />
  В чем ограничения такого метода:
-<ul>
 <li>Использование глобальных данных. Это обозначает, что при вызове программы без глобальных переменных, вызов функций из других сегментов попросту невозможен. При попытке вызвать произойдет обращение к несуществующей области глобалных данных и Fatal Alert неизбежен.</li>
 <li>Этот способ никак не расширяет область глобальных данных.</li>
 <li>Проблемы с доступом к константным данным. Константные данные могут оказаться в другом сегменте и тебовать наличия глобальных данных.</li>
 <li>Неявные функции и методы класса. C++ богат на неявную генерацию неявного кода. Следует контролировать куда будет помещен код темплейтов и не инлайновых инлайнов.</li>
 </ul>
  Подробное описание мультисегментной архитектуры GCC здесь:
 <a href="http://prc-tools.sourceforge.net/doc/prc-tools_3.html" class="external" target="_blank">http://prc-tools.sourceforge.net/doc/prc-tools_3.html</a>
 <p />
 <p />
  Существует альтернативный способ создания мультисегментных приложений с помощью утилиты multilink. Смотри описание здесь:
 <a href="http://www.djw.org/product/palm/multilink/" class="external" target="_blank">http://www.djw.org/product/palm/multilink/</a>
 <p />
  Multilink использует другую идею:
-<ul>
 <li>Исходные файлы компилируются как обычно. Не нужно указывать сегменты в исходном коде</li>
 <li>Утилита получает на вход объектные файлы и необязательный список разбиения функций по сегментам.</li>
 <li>Утилита разбивает все функции по сегментам по списку и добивает оставшиеся до указанного размера сегментов.</li>
 <li>Если функция foo из сегмента segA вызывает bar из сегмента srgB, то в segA добавляется заглушка для bar, вызывающая bar.</li>
 <li>Для вычисления адреса bar используются данные, которые хранятся в feature memory. Тем самым наличие глобальных данных необязательно.</li>
 <li>Полученные сегменты добавляются в программу.</li>
 </ul>
 <p />
  У этого решения есть один большой минус - невозможен доступ к константным данным из другого сегмента.
 <p />
 <p />
 </ow:body>
 </ow:page>
 </ow:wiki>