Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Няет текущий процесс новым процессом; а с другой - следит за использование процессора процессами и заставляет их переключаться, если они занимают процессор слишком долго.



То, как планировщик Linux определяет, какому процессу передавать управление, подробно описано в гл. 7, «Планировщик и синхронизация ядра»; тем не менее, если го­ворить кратко, планировщик определяет приоритеты на основе прошлого быстродействия (сколько процессорного времени процесс занимал ранее) и критического характера бы­стродействия для процесса (прерывания имеют более критический характер, чем ведение лога системы).

Помимо этого, планировщик Linux управляет выполнением процессов на многопро­цессорной машине (SMP). Существует несколько интересных особенностей для сбалан­сированной загрузки нескольких процессоров, таких, как привязка процесса к определен­ному процессору. Как было сказано ранее, базовая функциональность планировщика ос­тается идентичной планировщику системы с одним процессором.

Драйверы устройств Linux

Драйверы устройств - это интерфейсы для работы ядра с жесткими дисками, памятью, звуковыми картами, сетевыми картами и другими устройствами ввода и вывода.

Ядро Linux обычно включает несколько драйверов по умолчанию; Linux не будет слишком полезен, если не сможет принять ввод с клавиатуры. Драйверы устройств выде­лены в отдельный модуль. Несмотря на то что Linux имеет монолитное ядро, он сохраняет высокую степень модульности, позволяя динамическую загрузку каждого драйвера. Тем не менее стандартное ядро может оставаться относительно небольшим и постепенно рас­ширяться в зависимости от конфигурации системы, на которой запущен Linux.

В ядре Linux 2.6 драйверы устройств применяют два основных способа отображения их статуса пользователю системы: файловые системы /pros и /sys. При этом /ргос обычно применяется с целью отладки и слежения за устройствами, a /sys используется для изменения настроек. Например, если у вас есть радиотюнер на встроенном Linux-устройстве, вы можете видеть частоту по умолчанию и возможность ее изменения в раз­деле устройств в sysf s.

В гл. 5, «Ввод-вывод», и 10, «Добавление вашего кода в ядро», мы подробно рас­смотрим драйверы устройств для символьных и блочных устройств. Точнее говоря, мы коснемся драйвера устройства /dev/random и посмотрим, как он собирает информацию с других устройств Linux-системы.

Переносимость и архитектурные зависимости

По мере рассмотрения «внутренностей» ядра Linux время от времени мы будем обсуж­дать некоторые аспекты основного оборудования или архитектуры. Кроме того, ядро Linux - это большая совокупность кода, запускаемая на определенном типе процессоров и поэтому обладающая точными знаниями об этом процессоре (или процессорах),



Глава 1 • Обзор


включая набор инструкций и возможности. Тем не менее от каждого программиста ядра или системного программиста не требуется быть экспертом в микропроцессорах благо­даря удачной идее многослойного (layered) строения ядра, что позволяет отлаживать мно­гие возникающие проблемы прямо по мере их возникновения.

Ядро Linux создано таким образом, чтобы уменьшить количество аппаратно-зависи-мого кода. Когда требуется взаимодействие с аппаратной частью, вызываются соответст­вующие библиотеки, отвечающие за выполнение отдельных функций на данной архитек­туре. Например когда ядро хочет выполнить переключение контекста, оно вызывает функ­цию switch__to (). Так как ядро компилируется под конкретную архитектуру (напри­мер, PowerPC или х86), оно линкуется (во время компиляции) с соответствующими include-файлами include/asm-ppc/system.h*uiH include/asm-i386/system.h соответственно. Во время загрузки архитектурно-зависимый код инициализации выпол­няет вызов к Firmware BIOS (BIOS - это программное обеспечение для загрузки, описан­ное в гл. 9, «Построение ядра Linux»).

В зависимости от целевой архитектуры с аппаратным обеспечением взаимодейст­вуют различные слои программного обеспечения. Код ядра, ответственный за работу с этим аппаратным обеспечением, находится на более высоком слое.

Благодаря этому ядро Linux можно назвать портабелъным (portable) на различные архитектуры. Ограничения проявляются в тех случаях, когда невозможно портировать драйверы, по причине того, что такое аппаратное обеспечение несовместимо с данной архитектурой или она является недостаточно популярной для портирования на нее драй­веров. Для создания драйвера устройства программист должен иметь спецификацию дан­ного аппаратного обеспечения на уровне регистров. Не все производители предостав­ляют подобную документацию из-за проприетарного характера этого аппаратного обес­печения. Это в некоторой степени ограничивает распространение Linux на различные архитектуры.

Резюме

В этой главе представлен краткий обзор и описание тем, которые мы далее рассмотрим более подробно. Также мы упомянули некоторые особенности Linux, которым он обязан своей популярностью, и некоторые его недостатки. В следующей главе описываются ба­зовые инструменты для эффективного изучения ядра Linux.

Упражнения

1. В чем разница между системой UNIX и UNIX-клоном?

2. Что означает термин «Linux on Powen>?

3. Что такое пользовательское пространство? Что такое пространство ядра?


Упражнения



4. Что является интерфейсом к функциональности ядра из пространства пользователь­ских программ?

5. Как связаны пользовательский UID и имя пользователя?

6. Перечислите способы связи файлов с пользователями.

7. Перечислите типы файлов, поддерживаемых Linux.

8. Является ли оболочка частью операционной системы?

9. Для чего нужны защита файла и его режимы?

10. Перечислите виды информации, которую можно найти в структуре, хранящей мета­данные.

11. В чем заключается основное различие между символьными и блочными устройст­вами?

12. Какие подсистемы ядра Linux позволяют ему работать как многопоточная система?

13. Каким образом процесс становится родителем другого процесса?

14. В этой главе мы рассмотрели два иерархических дерева: дерево файлов и дерево процессов. В чем они похожи? Чем они отличаются?

15. Связаны ли Ш процесса и ID пользователя?

16. Для чего процессам назначаются приоритеты? Все ли пользователи могут изменять приоритеты процессов? Если могут или не могут, то почему.

17. Используются ли драйверы устройств только для добавления поддержки нового ап­паратного обеспечения?

18. Что позволяет Linux быть портируемой на разные архитектуры системой?


Глава



Исследовательский инструментарий

В этой главе:

■ 2.1 Типы данных ядра

? 2.2 Ассемблер

? 2.3 Пример языка ассемблера

? 2.4 Ассемблерные вставки

? 2.5 Необычное использование языка С

? 2.6 Короткий обзор инструментария для исследования ядра

? 2.7 Говорит ядро: прослушивание сообщений ядра

? 2.8 Другие особенности

? Резюме

? Проект: Hellomod

? Упражнения



Глава 2 • Исследовательский инструментарий


В

этой главе приведен обзор основных конструкций программирования под Linux и описаны некоторые методы взаимодействия с ядром. Мы начнем с обзора ос­новных типов данных Linux, используемых для эффективного хранения и получения информации, методов программирования и основ языка ассемблера. Это даст нам фундамент для более подробного анализа ядра в следующих главах. Затем мы опи­шем, как Linux компилирует и собирает исходный код в исполнимый код. Это будет полезно для понимания кросс-платформенного кода и заодно познакомит вас с GNU-набором инструментов. После этого будет описано несколько методов получения информации от ядра Linux. Мы проведем как анализ исходного и исполнимого кода, так и вставку отладочных сообщений в ядро Linux. Эта глава представляет собой сборную солянку обзора и комментариев по поводу принятых в Linux соглашений1.

Типы данных ядра

Ядро Linux содержит множество объектов и структур, за которыми нужно следить. Для примера можно привести страницы памяти, процессы и прерывания. Способность бы­стро находить каждый из объектов среди всех остальных является залогом эффективно­сти системы. Linux использует связанные списки и деревья бинарного поиска (вместе с набором вспомогательных структур), для того чтобы, во-первых, сгруппировать объек­ты внутри отдельных контейнеров и, во-вторых, для эффективного поиска отдельного элемента.

Связанные списки

Связанные списки (linked list) - это распространенные в компьютерной науке типы данных, повсеместно используемые в ядре Linux. Обычно в ядре Linux связанные списки реализуются в виде циклических двусвязных списков (рис. 2.1). Поэтому из каждого эле­мента такого списка мы можем попасть в следующий или предыдущий элемент. Весь код связанных списков можно посмотреть в include/linux/list.h. Этот подраздел описывает основные особенности связанных списков.

Связанный список инициализируется с помощью макросов LIST_HEAD и INIT_ LIST_HEAD:

include/linux/list.h

28 struct list_head {

1 Мы еще не углубляемся в глубины ядра. Здесь представлен обзор инструментов и концепций, необходимых для навигации в коде ядра. Если вы являетесь более опытным хакером, вы можете пропустить эту главу и сразу перейти к «внутренностям» ядра, описание которых начинается в гл. 3, «Процессы: принципиальная модель выполнения».


Типы данных ядра



2 9 struct list_head *next, *prev;
30 };

32 #define LIST_HEAD_INIT(name) { & (name), & (name) }

3 4 #define LIST_HEAD(name) \

35 struct list_head name = LIST_HEAD_INIT(name) 36

37 #define INIT_LIST_HEAD(ptr) do { \

38 (ptr)-> next = (ptr); (ptr)-> prev = (ptr); \

39 } while (0)

Строка 34

Макрос LIST_HEAD создает голову связанного списка, обозначенную как name.

Строка 37

Макрос INIT_LIST_HEAD инициализирует предыдущий и следующий указатели структуры ссылками на саму себя. После обеих этих вызовов паше содержит пустой двусвязный список1.

 

 

 

  Head  
с prev
next
     

Рис. 2.1. Связанный список после вызова макроса INITJLISTJiEAD

Простые стек и очередь могут быть реализованы с помощью функций list_add () и list_add_tail () соответственно. Хорошим примером может послужить сле­дующий отрывок из рабочего кода очереди:

kernel/workqueue.с

330 list_add(& wq-> list, & workqueues);

Ядро добавляет wq-> lis t к общесистемному списку рабочей очереди, workqueues. Таким образом, workqueues - это стек очередей.

Аналогично следующий код добавляет work-> entry в конец списка cwq-> worklist. При этом cwq-> worklist рассматривается в качестве очереди:

Пустой связанный список определяется как список, для которого head-> next указывает на голову списка.



Глава 2 • Исследовательский инструментарий


kernel/workqueue.с

84 list_add_tail(& work-> entry, & cwq-> worklist);

Для удаления элемента из очереди используется list_del (), которая получает удаляемый элемент в качестве параметра и удаляет элемент с помощью простой модифи­кации следующего и предыдущего узлов таким образом, чтобы они указывали друг на друга. Например, при уничтожении рабочей очереди следующий код удаляет рабочую очередь из общесистемного списка рабочих очередей:

kernel/workqueue.с

382 list_del(& wq-> list);

В include/linux/list. h находится очень полезный макрос list_f or__each_ entry:

include/linux/list.h

349 /*

350 * list_for__each_entry - проход по списку указанного типа

351 * @pos: type * to используется как счетчик цикла. 3 52 * @head: голова списка.

 

353 * ©member: имя list_struct внутри структуры.

354 */

355 tdefine list_for__each__entry(pos, head, member)

356 for (pos = list_entry((head)-> next, typeof(*pos), member),

357 prefetch(pos-> member.next);

358 & pos-> member! = (head);

359 pos = list__entry(pos-> member.next, typeof(*pos), member), 3 60 prefetch(pos-> member.next))

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

kernel/workqueue.с

59 struct workqueue_jstruct {

60 struct cpu_workqueue__struct cpu__wq[NR__CPUS];

61 const char *name;

62 struct list_head list; /* Пустая в однопоточном режиме */

63 };


Типы данных ядра



466 case CPU_ONLINE:

467 /* Удаление рабочих потоков. */

468 list_for_each__entry(wq, Sworkqueues, list)

469 wake_up_process(wq-> cpu_wq[hotcpu].thread);

470 break;

Макрос раскрывает и использует список list_head с помощью структуры workqueue_structwq для обхождения всех списков, головы которых находятся в рабо­чих очередях. Если это кажется вам немного странным, помните, что нам не нужно знать, в каком списке мы находимся, для того чтобы его посетить. Мы узнаем, что достигли кон­ца списка тогда, когда значение указателя на следующий элемент текущего вхождения бу­дет указывать на голову списка. Рис. 2.2 иллюстрирует работу списка рабочих очередей1.


workqueue_struct


Workqueue.struct


Workqueue.struct


 


*н cpu_wq


*\ cpu_wq


*J cpujwq


 


Name


Name


Name


 


Liist

Prev


Liist

Prev


Liist

Prev


 


Next


Next


Next


Рис. 2.2. Список рабочих очередей

Дальнейшее усовершенствование связанного списка заключается в такой реализа­ции, где голова списка содержит только один указатель на первый элемент. В этом состоит главное отличие от двусвязного списка, описанного в предыдущем разделе. Используе­мый в хеш-таблицах (описанных в гл. 4, «Менеджмент памяти») единственный указатель головы не имеет указателя назад, на хвостовой элемент списка. Таким образом достигает­ся меньший расход памяти, так как указатель хвоста в хеш-таблицах не используется.

include/linux/list.h 484 struct hlist_head {

1 Кроме этого, можно использовать list_for_each_entry_reverse О для посещения элементов списка в обратном порядке.



Глава 2 • Исследовательский инструментарий


485 struct hlist_node *first;

486 };

488 struct hlist_node {

489 struct hlist_node *next, **pprev;

490 };

492 #define HLIST_HEAD_INIT {.first = NULL }

493 #define HLIST_HEAD(name) struct hlist_head name = {.first = NULL }

Строка 492

Макрос HLIST_HEAD_INIT устанавливает указатель first в указатель на NULL.

Строка 493

Макрос HLIST_HEAD создает связанный список по имени и устанавливает указа­тель first в указатель на NULL.

Этот список создается и используется ядром Linux в рабочей очереди, как мы увидим далее в планировщике, таймере и для межмодульных операций.

Поиск

Подразд. 2.1.1 описывает объединение элементов в список. Упорядоченный список эле­ментов сортируется по значению ключа каждого элемента (например, когда каждый элемент имеет ключ, значение которого больше предыдущего элемента). Если мы хотим обнаружить определенный элемент (по его ключу), мы начнем с головы и будем переме­щаться по списку, сравнивая значение его ключа с искомым значением. Если значения не равны, мы переходим к следующему элементу, пока не найдем подходящий. В этом при­мере время, необходимое для нахождения нужного элемента, прямо пропорционально значению ключа. Другими словами, такой линейный поиск выполняется тем дольше, чем больше элементов в списке.

Большое 0

Для теоретической оценки времени работы алгоритма, необходимого для поиска заданного ключа поиска, используется нотация большое О (Big-O). Она показывает наихудшее время поиска для заданного количества элементов (п). Для линейного поиска Big-О нотация показы­вает 0(п/2), что означает среднее время поиска, т. е. перебор половины ключей списка. Источник: Национальный институт стандартов и технологий (www.nist.org)

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


2.1 Типы данных ядра



2.1.3 Деревья

Используемые в Linux для управления памятью деревья позволяют эффективно получать доступ и манипулировать данными. В этом случае эффективность измеряется тем, на­сколько быстро мы сможем сохранять и получать отдельные группы данных среди дру­гих. В этом подразделе представлены простые деревья, и в том числе красно-черные деревья, а более подробная реализация и вспомогательные элементы показаны в гл. 6, «Файловые системы». Деревья состоят из узлов (nodes) и ребер (edges) (см. рис. 2.3). Узлы представляют собой элементы данных, а ребра - связь между узлами. Первый, или верхний, узел является корнем дерева, или корневым (root) узлом. Связь между узлами описывается как родителифагеЫ)\ дети (child), или сестры (sibling), где каждый ребе­нок имеет только одного родителя (за исключением корня), каждый родитель имеет од­ного ребенка или больше детей, а сестры имеют общего родителя. Узел, не имеющий де­тей, называется листом (leaf). Высота (height) дерева - это количество ребер от корня до наиболее удаленного листа. Каждая строка наследования в дереве называется уровнем (level). На рис. 2.3 b и с находятся на один уровень ниже a, a d, e и f на два уровня ниже а. При просмотре элементов данного набора сестринских узлов упорядоченные деревья со­держат элементы сестры с наименьшим значением ключа слева и наибольшим справа. Деревья обычно реализуются как связанные списки или массивы, а процесс перемещения по дереву называется обходом (traversing) дерева.

Корень (Родитель)



(Ь) Дочерний узел узла (а) и родитель узлов (d, e, f)

■ ^Х. (с) Дочерний лист узла (а)

Ребра

Дочерние листья

 


Рис. 2.3. Дерево с корнем

Бинарные деревья

До этого мы рассмотрели поиск ключа с помощью линейного поиска, сравнивая наш ключ на каждой итерации. А что если с каждым сравнением мы сможем отбрасывать по­ловину оставшихся ключей?

Бинарное дерево (binary tree) в отличие от связанного списка является иерархиче­ской, а не линейной структурой данных. В бинарном дереве каждый элемент или узел ука-



Глава 2 • Исследовательский инструментарий


зывает на левый и правый дочерние узлы и, в свою очередь, каждый дочерний узел указы­вает на левого и правого ребенка и т. д. Главное правило сортировки узлов заключается в том, чтобы у каждого левого дочернего узла значение ключа было меньше, чем у родите­ля, а у правого больше или равно родительскому. В результате применения этого правила мы знаем, что для значения ключа в данном узле левый дочерний узел и его потоки со­держат меньшие значения ключей, чем у данного, а правый и его потомки - большее или равное значение ключа.

Сохраняя данные в бинарном дереве, мы уменьшаем данные для поиска на половину в каждой итерации. В нотации Big-О его производительность (с учетом количества иско­мых элементов) оценивается как О log(n). Сравните этот показатель с линейным поиском со значением Big-0 0(n/2).

Алгоритм, используемый для прохода по бинарному дереву, прост и отлично подхо­дит для рекурсивной реализации, так как в каждом узле мы сравниваем значение нашего ключа и переходим в левое или правое поддерево. Далее мы обсудим реализации, вспомо­гательные функции и типы бинарных деревьев.

Как только что говорилось, узел бинарного дерева может иметь только одного лево­го, только одного правого потомка, обоих (левого и правого) потомков или не иметь по­томков. Для упорядоченного бинарного дерева действует правило, что для значения узла (х) левый дочерний узел (и все его потомки) имеют значения меньше х, а правый дочерний узел (и все его потомки) имеют значение больше х. Следуя этому правилу, если в бинарное дерево вставляется упорядоченный набор значений, оно превращается в линейный спи­сок, что приводит к относительно медленному поиску значений. Например, если мы соз­даем бинарное дерево со значениями [0, 1, 2, 3, 4, 5, 6], 0 будет находиться в корне, 1 больше 0 и будет его правым потомком; 2 больше 1 и будет его правым потомком; 3 будет правым потомком 2 и т. д.

Сбалансированным по высоте (height-balanced) бинарным деревом является такое дерево, которое не имеет листьев, более удаленных от корня, чем остальные. По мере до­бавления узлов в дерево его нужно перебалансировать для более эффективного поиска; что выполняется с помощью поворотов (rotation). Если после вставки данный узел (е) имеет левого ребенка с потомками на два уровня больше, чем другие листья, мы должны выполнить правый поворот узла е. Как показано на рис. 2.4, е становится родителем h и правый ребенок е становится левым ребенком h. Если выполнять перебалансировку по­сле каждой вставки, мы можем гарантировать, что нам нужен только один поворот. Это правило баланса (когда ни один из листьев детей не должен находиться на расстоянии больше одного) известно как AVL-дерево [в честь Дж. М. Адельсона-Велски (G. M. Adel-son-Velskii) и Е. М. Лендис (Е. М. Landis)].


Типы данных ядра



Рис. 2.4. Правый поворот

Красно-черные деревья

Красно-черное дерево, похожее на AVL-дерево, используется в Linux для управления па­мятью. Красно-черное дерево - это сбалансированное бинарное дерево, в котором каж­дый узел окрашен в красный или черный цвет. Вот правила для красно-черного дерева:

Все узлы являются либо красными, либо черными.

Если узел красный, оба его потомка - черные.

Все узлы-листья - черные.

При перемещении от корня до листа каждый путь содержит одинаковое количество черных узлов.

Как AVL-, так и красно-черные деревья имеют производительность О log(n) (в нотации Big-O), зависящую от количества вставленных данных (сортированных/не­сортированных) и поиска; каждый тип обладает своими преимуществами. [В Интернете можно найти несколько интересных книг, посвященных производительности деревьев би­нарного поиска (BST).]

Как говорилось ранее, в компьютерной науке используются многие структуры дан­ных и связанные с ними алгоритмы поиска. Целью этого раздела является помочь вам в ваших исследованиях концепций и структур данных, используемых для организации данных в Linux. Понимание основ списков и деревьев поможет вам понять более сложные операции, такие, как управление памятью и очереди, которые обсуждаются в следующей главе.



Глава 2 • Исследовательский инструментарий


Ассемблер

Linux - это операционная система. Поэтому его часть тесно связана с процессором, на ко­тором он работает. Авторы Linux проделали огромную работу по минимизации процес­сорно- (и архитектурно-) зависимого кода, стараясь писать как можно менее архитек­турно-зависимый код. В этом разделе мы рассмотрим следующее:

• Каким образом некоторые функции реализуются на х86- и PowerPC-архитектурах.

• Как использовать макросы и встроенный ассемблерный код.

Целью этого раздела является раскрытие основ, необходимых вам для того, чтобы разобраться в архитектурно-зависимом коде ядра и не заблудиться в нем. Мы оставим серьезное программирование на языке ассемблера для других книг. Также мы рассмотрим некоторые тонкости применения языка ассемблера: встроенный ассемблер.

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

PowerPC

PowerPC - это архитектура с ограниченным набором вычислительных инструкций (Re­duced Instruction Set Computing, RISC). Архитектура RICS предназначена для увеличе­ния производительности за счет упрощения выполнения набора инструкций за несколько циклов процессора. Для того чтобы воспользоваться преимуществами параллельных (су­перскалярных) инструкций аппаратного обеспечения, некоторые из этих инструкций, как мы вскоре увидим, далеко не так просты. Архитектура PowerPC совместно разработана ЮМ, Motorola и Apple. В табл. 2.1 перечислен пользовательский набор регистров PowerPC.

Таблица 2.1. Набор регистров PowerPC

 

Имя регистра Ширина регистра Функция Количество регистров
  32 бита 64 бита    

CR 32 32 Регистр состояния 1

LR 32 64 Регистр связи 1

CTR 32 64 Регистр счетчика 1

GPR[0...31] 32 64 Регистр общего 32

назначения

XER 32 64 Регистр исключений с 1

фиксированной точкой

FPR[0...31] 64 64 Регистр с плавающей 32

точкой


Ассемблер



Таблица 2.I. Набор регистров PowerPC (Окончание)

FPSCR 32 64 Регистр контроля 1

управления с плавающей точкой

Табл. 2.2 иллюстрирует применение бинарного интерфейса приложений для общих регистров и регистров с плавающей точкой. Переменные регистры могут использоваться в любое время, а постоянные-только для выполнения вызовов предусмотренных функций.

Бинарный интерфейс приложений [Application Binary Interface (ABI)]

ABI - это набор соглашений, позволяющий компоновщику объединять отдельные скомпи­лированные модули в один юнит без перекомпиляции, соглашений на вызовы, машинный интерфейс и интерфейс операционной системы. Помимо всего прочего, ABI определяет би­нарный интерфейс между юнитами. Существует несколько разновидностей PowerPC ABI. Обычно они связаны с целевой операционной системой и/или оборудованием. Эти вариации и расширения основаны на разработанной в AT& T документации UNIX System V Application Binary Interface и ее более поздних вариациях из Santa Cruz*Operation (SCO). Соответствие ABI позволяет компоновать объектные файлы, откомпилированные различными компиляторами.

Таблица 2.2. Использование регистров ABI

 

Регистр Тип Использование
гО Переменный Пролог/эпилог, языково-зависимые
г1 Специальный Указатель на стек
г2 Специальный ТОС
гЗ-г4 Переменный Передаваемые параметры для ввода-вывода
г5-г10 Переменный Передаваемые параметры
rll Переменный Указатель на окружение
г12 Переменный Обработка исключений
г13 Постоянный Зарегистрирован для вызовов
г14-г31 Постоянный Зарегистрирован для вызовов
ГО Переменный Рабочий
fl Переменный Первый параметр с плавающей точкой, возвращает первое скалярное значение с плавающей точкой


Глава 2 • Исследовательский инструментарий


Таблица 2.2. Использование регистров ABI (Окончание)

f2-f4 Переменный Параметры со 2-го по 4-й, возвращают скалярное значение

с плавающей точкой

F5-A3 Переменный Параметры с 5-го по 13-й

fl4-f31 Постоянный Зарегистрирован для вызовов

Архитектура PowerPC с 32 битами использует инструкции длиной 4 бита, выровнен­ные по слову. Она оперирует байтами, полусловом, словом и двойным словом. Инструк­ции делятся на переходы, инструкции с фиксированной точкой и с плавающей точкой.

Условные инструкции

Регистр состояния (condition register, CR) применяется для всех условных операций. Он разбит на 8 4-битовых полей, которые можно явно изменить инструкцией move, неявно в результате выполнения инструкции или чаще всего в результате инструкции сравнения.

Регистр связывания (link register, LR) используется в некоторых видах условных операций для получения адреса перехода и адреса возврата из условной инструкции.

Регистр счетчика (count register, CTR) хранит счетчик циклов, увеличиваемый с помощью некоторых условных инструкций. Кроме этого, CTR хранит адрес перехода для некоторых из условных инструкций.

В дополнение к CTR и LR условные инструкции PowerPC могут выполнять переходы по относительному или абсолютному адресу. При использовании расширенных мнемоник становятся доступными еще множество различных условных и безусловных инструкций перехода.


Поделиться:



Популярное:

  1. A. если насчитывает более 10 членов.
  2. Cтереодиисплей. 3D мониторы.
  3. E) микроэкономика изучает отношения между людьми в процессе эффективного использования ограниченных ресурсов
  4. E) Способ взаимосвязанной деятельности педагога и учащихся, при помощи которого достигается усвоение знаний, умений и навыков, развитие познавательных процессов, личных качеств учащихся.
  5. Hfr-клетки. Использование их в картировании бактериальных генов.
  6. I. 1. Трудности в понимании аристотелевского катарсиса.
  7. I. Использование средств индивидуальной и коллективной защиты в ЧС.
  8. I.3. От медицинской интерпретации катарсиса в 19в. до современного противоречивого понимания.
  9. II. Методы несанкционированного доступа.
  10. III. Аполлоническое и дионисийское начало.
  11. IV. Организация функционирования сооружений и устройств железнодорожного транспорта
  12. IV. Сравните параллельные тексты, проанализировав использование приема приближенного перевода.


Последнее изменение этой страницы: 2016-03-25; Просмотров: 725; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.106 с.)
Главная | Случайная страница | Обратная связь