
- •Архитектура современной вычислительной системы (обзор)
- •Кэши ассоциативные, с прямым отображением и множественно-ассоциативные
- •Представление бинарных данных
- •Режимы работы процессоров семейства i8086+
- •Регистры i8086+
- •Формат инструкции
- •Некоторые инструкции ЦПУ (не включая инструкции FPU, MMX, SSEn и пр.)
- •Формирование кодов основных инструкций i8086+
- •Соответствие мнемоники машинным кодам на примере инструкции пересылки (mov)
- •Режим реальных адресов i8086 (real mode)
- •Синтаксис основных ассемблеров (Intel и AT&T) семейства процессоров i8086+
- •Адреса: короткие, ближние, дальние; перемещаемые записи
- •Сегменты, секции, модели памяти, страницы
- •Переходы, вызовы процедур
- •Символы и макросы
- •Структура физического адресного пространства режима реальных адресов
- •Простейший пример BIOS
- •Некоторое оборудование IBM PC
- •Инициализация контроллера прерываний
- •Инициализация контроллеров клавиатуры PS/2
- •Инициализация PS/2 мыши
- •Инициализация таймера 8253/8254
- •Работа с последовательным интерфейсом UART
- •Программирование контроллера DMA 8257/8237
- •Прерывания в SMP системе; измерение времени
- •Инициализация локального контроллера прерываний (LAPIC)
- •Инициализация контроллера прерываний ввода-вывода (IO APIC)
- •Сегментная модель защищенных режимов i286...x64
- •Общая структура дескриптора
- •Cегмент состояния задачи; переключение стеков
- •«Нереальный 8086»
- •Системные вызовы
- •Структура адресного пространства многопоточного приложения (C, расширение MSVC) с обработкой исключений (Win32).
- •Структура адресного пространства многопоточного приложения (C++) с обработкой исключений (Posix Threads (NPTL); Linux; IA-32)
- •Страничная модель защищенных режимов i386...x64
- •Соглашения о вызовах C/C++ (платформы IA-32, x64)
- •Пример программы, демонстрирующей различные соглашения о вызовах.
- •Основные средства управления адресным пространством, основанные на страничном механизме
- •Запрет на исполнение данных
- •Пример использования уязвимости типа «переполнение буфера в стеке»
- •Проецирование файлов.
- •Императивный способ управления проецированием.
- •Пример создания разделяемого проецирования для межпроцессного взаимодействия
- •Исполняемые файлы и динамические библиотеки
- •Построение динамических библиотек
- •Загрузка библиотек на этапе исполнения.
- •Экспорт, импорт, перемещаемые записи в Windows
- •Экспорт, импорт, перемещаемые записи в Posix
- •POSIX. Позиционно-независимый код в архитектуре IA-32.
- •Построение и использование статических библиотек объектных файлов
- •Встроенный ассемблер; понятие барьеров оптимизации и барьеров памяти.
- •Пример измерения коротких интервалов времени
- •SMP, критические секции и взаимные блокировки
- •Литература

Страничная модель защищенных режимов i386...x64 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Примечания: |
|
|
|
|
|
|
|||||||||||||||||||
Логический адрес |
|
|
|
|
|
|
|
|
|
63 |
|
|
48 47 |
|
39 38 |
30 29 |
|
21 20 |
12 11 |
0 |
|
|
|
- Размер линейного адреса L бит. |
|
|
|
|||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- Линейный адрес разбивается на: |
|
|
|
|||||||||||||||||||||||||
|
|
|
15 |
0 |
31 |
|
0 |
|
|
|
|
|
|
|
|
<signs> |
|
#PML4E#PDPTE |
|
|
|
смещение |
|
|
|
|
|
|
|
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- младшие P бит — смещение на странице. |
|
|
||||||||||||||||||||||
|
|
|
SSSS : |
OOOO OOOO |
|
|
|
|
|
|
|
|
<signs> |
|
#PML4E#PDPTE #PDE |
|
|
смещение |
|
|
|
|
|
|
||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- несколько (k) частей, длиной не более N бит каждая, |
||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<signs> |
|
#PML4E#PDPTE #PDE |
|
#PTE |
смещение |
|
|
|
||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
задающие индексы в иерархических таблицах страниц. |
|||||||||||||||||||||||
|
|
(селектор) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#PDE |
|
#PTE |
смещение |
|
|
|
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- Размер страницы 2P байт. |
|
|
|
|
||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||
|
|
|
Сегментное |
|
|
|
|
Таблица |
|
|
|
|
|
|
|
|
|
|
31 |
|
22 21 |
12 11 |
0 |
|
|
|
- Размер физического адреса M бит. |
|
|
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#PDE |
|
|
смещение |
|
|
|
|
|
|
||||||||||||||||||
|
|
|
преобразование |
|
|
|
4го уровня |
|
Таблица |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Большая |
|
- На одной странице размещается 2 *8/M записей PTE; т.е. |
||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#PDE |
|
#PTE |
смещение |
|
страница |
1G |
N=log2(2 |
P |
*8/M). |
|
|
|
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
указателей |
|
|
|
|
|
|
|
данных |
|
|
|
|
|
|
|
||||||||||||||
Линейный адрес |
|
|
|
|
|
PML4E |
|
|
на каталоги |
|
|
|
|
|
10 |
|
|
10 |
12 |
|
|
|
|
- все страницы начинаются на границе, кратной размеру |
||||||||||||||||||||
|
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
данные |
|
страницы (т.е. младшие P битов PTE,PDE и т.п. записей не |
|||||||||||||||
|
|
|
63 |
47 32 |
23 |
|
|
|
|
|
|
|
|
PDPTE |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
используются для задания адреса кадра). |
|
|
|||||||||||||||
|
|
|
SSSS FFFF FFFF FFFF |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Каталог |
|
|
|
|
|
|
|
|
|
|
Для i80386 (Pentium без PAE и без PSE-36) |
|
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Большая |
|
|
|||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
страниц |
|
|
|
|
|
|
|
|
|
|||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
страница |
|
L=32, M=32, k=2, N=10, P=12 |
|
|
|
|||||||
|
|
|
Страничное |
|
63 |
52 51 |
32 31 |
|
12 11 |
0 |
|
|
|
|
|
PDE |
|
|
|
|
|
|
|
|
данных 4/2M |
|
|
|
||||||||||||||||
|
|
|
|
0 |
|
CR3 каталог страниц |
? |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
страница 4K, формат линейного адреса 10-10-12 |
|
|
|||||||||||||||||
|
|
|
преобразование |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
данные |
|
большая страница 4M; формат 10-22 |
|
|
|
||||||||||||||||||
|
|
|
|
|
|
PAE |
каталог страниц xx000 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Для Pentium с включенным PAE |
|
|
|
|||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Таблица |
|
|
|
|
|
|
|
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
каталог страниц |
? |
|
PCDPWT |
|
|
|
|
|
|
|
|
|
|
Большая |
|
|
|
|
|
|||||||||||||
Физический адрес |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
страниц |
|
|
|
L=32, M=64 (используется 36), k=3, N=9, P=12 |
|
||||||||||||||||
|
0 |
|
|
0 |
|
CR0 |
|
MSW |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
страница |
4K |
|
|
||||||||||||||||
|
|
|
63 |
51 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
данных |
|
страница 4K, формат 2-9-9-12 |
|
|
|
|
|||||||||||
|
|
|
000F FFFF FFFF FFFF |
31 |
30 |
29 28 |
... 19 |
18 17 |
16 |
15 |
... |
|
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
|
|
|
|
PTE |
|
|
|
|
|
большая страница 2M, формат 2-9-21 |
|
|
|
||||||||||
|
|
|
4 PB |
|
|
|
|
|
|
|
|
|
|
|
данные |
|
|
Для x64 |
|
|
|
|
|
|
|
|
||||||||||||||||||
|
|
|
|
|
PG |
CD |
NW ... |
AM - |
WP - - |
- |
- - |
- |
NE |
ET |
TS |
EM MP PE |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||
|
|
|
|
|
|
|
|
PG=1 страничный режим |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
L=64 (исп. 48), M=64 (исп. 52), k=4, N=9, P=12 |
|
||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
страница 4K,формат 9-9-9-9-12 |
|
|
|
|
||||||||||||
|
|
|
|
|
|
|
|
|
CR2 адрес страничного отказа |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
страница 2M, формат 9-9-9-21 |
|
|
|
|
||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
страница 1G, формат 9-9-30 |
|
|
|
|
|||||||||||
|
|
|
|
|
|
|
|
|
|
0 |
|
CR4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Адрес кадра страницы |
|
|
|
|
|||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+ |
Атрибуты PTE, PDE, PDPTE, PML4E |
|
|
|||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||
|
|
|
|
|
|
|
|
31 |
30 |
|
|
... |
|
|
|
|
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
|
Смещение на странице |
P |
1: признак присутствия в ОЗУ |
|
|
|
|||||||||||||
|
|
|
|
|
|
|
|
– |
|
|
|
... |
|
|
|
|
– |
PAE PSE |
– |
– |
– |
– |
|
|
|
R/W 1: страница доступна для изменения |
|
|
||||||||||||||||
|
|
|
|
|
|
|
|
|
|
режим PAE разрешен |
флаг PDE.PS разрешен |
|
|
|
|
Физический адрес |
|
U/S 1: страница доступна только из нулевого кольца |
|
|||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PWT 1: кэш должен использовать сквозную запись |
|
|
|||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PTE, 4K |
|
|
|
|
||||||||
63 |
62 |
|
52 51 |
40 39 |
36 35 |
32 31 |
|
|
|
22 21 |
20 |
|
17 16 |
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
|
5 |
4 |
3 |
2 1 |
0 |
|
|
PCD |
1: запрещено кэширование этой страницы |
|
|
|||||||||
|
|
|
|
|
|
|
|
|
|
|
Адрес кадра |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IA-32 |
|
|
PAT |
1: использовать PCD-PWT как индекс атрибутов |
|
||||||||||
|
|
|
0 . . . 0 |
|
|
|
|
|
|
Адрес кадра |
|
|
|
|
|
|
|
Avl |
|
G |
PAT |
D |
A |
|
PCD PWT U/S R/W |
P |
IA-32 + PAE |
|
|
A |
1: было обращение |
|
|
|
|
|
||||||||
EXB |
|
Avl |
< . . . > |
|
|
|
|
Адрес кадра |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
x64 |
|
|
D |
1: страница была изменена |
|
|
|
|
||||||||
63 |
62 |
|
52 51 |
40 39 |
36 35 |
32 31 |
|
|
|
22 21 |
20 |
|
17 16 |
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
|
5 |
4 |
3 |
2 1 |
0 |
PDE |
|
|
PS |
1: признак большой страницы (2M, 4M, 1G) |
|
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
Адрес кадра |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IA-32 |
|
|
G |
1: глобальная таблица (запись сохраняется в TLB) |
|
||||||||||
|
|
|
0 . . . 0 |
|
|
|
|
|
|
Адрес кадра |
|
|
|
|
|
|
|
Avl |
|
G |
PS |
D |
A |
|
PCD PWT U/S R/W |
P |
IA-32 + PAE |
|
|
EXB |
1: запрет исполнения |
|
|
|
|
|
||||||||
EXB |
|
Avl |
< . . . > |
|
|
|
|
Адрес кадра |
|
|
|
|
|
|
|
|
|
|
|
=0 |
|
|
|
|
|
|
x64 |
|
|
AVL 1: доступны для разработчиков |
|
|
|
|||||||||||
63 |
62 |
|
52 51 |
40 39 |
36 35 |
32 31 |
|
|
|
22 21 |
20 |
|
17 16 |
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
|
5 |
4 |
3 |
2 1 |
0 |
PDE, страница 4/2M |
<...> биты адреса используются конкретными процессорами |
Длина |
||||||||||||
|
|
|
|
|
|
|
Адрес кадра |
|
|
0 . . . 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IA-32 |
|
|
CR0 |
CR4 |
CR4 |
MSR |
PDE |
PDPTE |
Платформа |
Размер |
||||||
|
|
|
|
|
|
|
Адрес кадра 31..22 |
0 . . . 0 |
Адрес 35...32 |
PAT |
|
Avl |
|
G |
PS |
D |
A |
|
PCD PWT U/S R/W |
P |
IA-32 + PSE36 |
|
|
PG |
PSE |
PAE |
LME |
PS |
PS |
и режим |
страницы |
адреса |
||||||||||||
|
|
|
0 . . . 0 |
|
|
|
Адрес кадра |
|
|
|
0 . . . 0 |
|
|
|
|
|
|
|
|
=1 |
|
|
|
|
|
|
IA-32 + PAE |
|
|
0 |
x |
|
x |
x |
x |
x |
i8086 |
откл. |
||||||
EXB |
|
Avl |
< . . . > |
|
|
Адрес кадра |
|
|
|
|
0 . . . 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
x64 |
|
|
1 |
0 |
|
0 |
x |
0 |
x |
386 |
4K |
32 |
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||
63 |
62 |
|
52 51 |
40 39 |
36 35 |
32 31 |
|
|
|
22 21 |
20 |
|
17 16 |
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
|
5 |
4 |
3 |
2 1 |
0 |
PDPTE |
|
|
1 |
1 |
|
0 |
x |
0 |
x |
586 |
4K |
32 |
||
|
|
|
0 . . . 0 |
|
|
|
|
|
|
Адрес кадра |
|
|
|
|
|
|
|
Avl |
|
G |
PAT |
D |
A |
|
PCD PWT U/S R/W |
P |
IA-32 + PAE |
|
|
1 |
1 |
|
0 |
x |
1 |
x |
586 PS |
4M |
32 |
|||||
EXB |
|
Avl |
< . . . > |
|
|
|
|
Адрес кадра |
|
|
|
|
|
|
|
|
|
|
|
1 |
1 |
|
0 |
x |
1 |
x |
586 PSE36 |
4M |
36 |
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
x64 |
|
|
|
|||||||||||||||||
63 |
62 |
|
52 51 |
40 39 |
36 35 |
32 31 |
30 29 |
22 21 |
20 |
|
17 16 |
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
|
5 |
4 |
3 |
2 1 |
0 |
PDPTE, страница 1G |
1 |
1 |
|
1 |
x |
0 |
0 |
586 PAE |
4K |
36 |
||||||
EXB |
|
Avl |
< . . . > |
|
Адрес кадра |
|
|
|
|
0 . . . 0 |
|
|
|
|
|
Avl |
|
G |
PS |
D |
A |
|
PCD PWT U/S R/W |
P |
x64 |
|
|
1 |
1 |
|
1 |
x |
1 |
0 |
586 PAE PS |
2M |
36 |
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
=1 |
|
|
|
|
|
|
PML4E |
|
|
1 |
1 |
|
1 |
1 |
0 |
0 |
x64 |
4K |
52 |
|
63 |
62 |
|
52 51 |
40 39 |
36 35 |
32 31 |
30 29 |
22 21 |
20 |
|
17 16 |
15 |
14 |
13 |
12 |
11 |
10 |
9 |
8 |
7 |
6 |
|
5 |
4 |
3 |
2 1 |
0 |
|
|
1 |
1 |
|
1 |
1 |
1 |
0 |
x64 PS |
2M |
52 |
|||||
EXB |
|
Avl |
< . . . > |
|
|
|
|
Адрес кадра |
|
|
|
|
|
|
|
Avl |
|
G |
PS |
D |
A |
|
PCD PWT U/S R/W |
P |
x64 |
|
|
1 |
1 |
|
1 |
1 |
x |
1 |
x64 PS |
1G |
52 |

Соглашения о вызовах C/C++ (платформы IA-32, x64) |
|
|
|
|
|
|
#ifdef __cplusplus |
||||||
Различия C и C++: |
|
|
|
|
|
|
|
|
|||||
В традиционном соглашении о вызовах языка C принято: |
|
|
|
|
|
extern «C» { |
|||||||
а) передача аргументов через стек, справа-налево (первый аргумент размещается в стеке последним) |
|
|
#endif |
|
|||||||||
б) освобождение фрейма от аргументов выполняет вызывающий код |
|
|
|
|
|
int __cdecl test(int x) |
|||||||
в) декорирование имен сводится к добавлению прочерка перед именем функции (т.е. _main и т.п.) |
|
|
{ |
|
|
||||||||
В случае C++ необходима поддержка перегрузки функций, поэтому используются сложные схемы декорирования имен, сохраняющие |
/* ... */ |
||||||||||||
информацию о пространстве имен, классе, типе возвращаемого результата и списке аргументов функции. Для экземплярных методов |
} |
|
|
||||||||||
классов используется неявный аргумент (обычно первый) — указатель this. |
|
|
|
|
#ifdef __cplusplus |
||||||||
Ключевое слово extern задает умолчания, применяемые в программе («C» или «CPP»); а также влияет на декорирование имен. |
|||||||||||||
} |
|
|
|||||||||||
Явное задание соглашения при описании функции влияет на способ передачи аргументов, но зачастую не влияет на декорирование. |
|
|
|||||||||||
#endif |
|
||||||||||||
Точное задание соглашение и декорирования — использование extern и модификаторов соглашения (cdecl, stdcall, fastcall). |
|
||||||||||||
|
|
|
|||||||||||
Различия между разными платформами и компиляторами: |
|
|
|
|
|
|
|
|
|||||
Компиляторы строго придерживаются принятых соглашений о вызовах только для функций, доступных из внешних модулей. Оптимизатор часто изменяет соглашение, |
|||||||||||||
принятое для локальных функций в части упрощения фрейма процедуры, передачи аргументов через регистры и использования регистров. |
|
||||||||||||
|
|
Microsoft-совместимые |
|
|
|
|
GCC |
|
|
|
|||
|
|
IA-32 |
|
x64 |
|
IA-32 /__attribute__((соглашение))/ |
x64 |
||||||
|
(default) |
__cdecl |
__stdcall |
__fastcall |
|
(default) |
cdecl |
stdcall |
|
fastcall |
|
||
сохраняемые |
|
EBX, EBP, ESI, EDI |
|
RBX, RBP, |
|
|
EBX, EBP, ESI, EDI |
|
|
RBX, RBP, |
|||
регистры |
|
|
|
|
RSI, RDI, |
|
|
|
|
|
|
R12-R15 |
|
|
|
|
|
|
R12-R15, |
|
|
|
|
|
|
|
|
|
|
|
|
|
XMM6-XMM15 |
|
|
|
|
|
|
|
|
передача |
[this в ECX] |
стек |
стек |
ECX |
RCX / XMM0 |
[this в стек] |
стек |
стек |
|
ECX |
RDI, RSI, |
||
аргументов |
стек |
|
|
EDX |
RDX / XMM1 |
стек |
|
|
|
EDX |
RCX, RDX, |
||
(в стек: |
|
|
|
стек |
R8 / XMM2 |
|
|
|
|
|
стек |
R8, R9, |
|
справа-налево) |
|
|
|
|
R9 / XMM3 |
|
|
|
|
|
|
XMM0-XMM7 |
|
|
|
|
|
|
стек |
|
|
|
|
|
|
стек |
|
освобождение |
вызывающий вызывающий |
функция |
функция |
вызывающий |
вызывающий |
вызывающий |
функция |
|
функция |
вызывающий |
|||
стека от |
|
|
|
|
|
|
|
|
|
|
|
|
|
аргументов |
|
EAX, EDX |
|
RAX |
|
|
EAX, EDX |
|
|
RAX, RDX |
|||
возврат |
|
|
|
|
|
|
|||||||
значений |
|
ST(0) |
|
XMM0 |
|
|
ST(0) |
|
|
|
ST(0), ST(1) |
||
возврат |
|
|
стек по указателю, переданном вызывающим кодом в неявном аргументе |
|
|
XMM0, XMM1 |
|||||||
|
|
|
|
|
|||||||||
структур |
|
|
(в C++ сопровождается неявным вызовом конструкторов копирования/деструкторов) |
|
|
|
|||||||
Формирование фрейма функции: |
сохранение регистров |
|
|
Способы передачи аргументов в стеке: |
|
||||||||
push |
%ebp |
|
... |
|
|
... |
|
|
|
||||
|
|
|
|
|
|
|
|
|
|||||
mov |
%esp, |
|
резервирование |
|
sub |
$XX, %esp |
sub |
|
$XX+max(N)*4, %esp |
||||
push |
%esi |
|
|
пространства |
|
... |
|
|
... |
|
|
|
|
sub |
$XX, %esp |
|
|
под локальные |
|
push |
argN |
|
mov |
|
argN, 4*(N-1)(%esp) |
||
... |
-4(%ebp), %esp |
|
переменные |
|
... |
arg1 |
|
... |
|
arg1, (%esp) |
|||
leal |
|
|
|
push |
|
mov |
|
||||||
pop |
%esi |
освобождение |
|
|
call |
_function |
call |
|
_function |
|
|||
pop |
%ebp |
|
фрейма |
|
|
add |
$4*N, %esp |
... |
|
|
|
||
ret |
[NN] |
от переменных |
|
|
... |
|
|
leal |
|
-4(%ebp), %esp |

Пример программы, демонстрирующей различные соглашения о вызовах.
1. Определяемые типы данных и конструкторы
Структура 'xy', содержащая два поля целого типа; в памяти будет занимать 8 байт (2*4).
Класс 'xx', содержащий одно поле (m_v), три экземплярных метода (конструктор, getxy и getsum), неэкземплярный метод (sumxy) и виртуальный деструктор; в
памяти будет занимать 8 байт (4 байта — поле + 4 байта — неявное поле-указатель на т.н. «таблицу виртуальных методов»). |
|
|
|
|||||||||||||||||
|
#ifdef __GNUC__ |
|
|
|
|
|
|
CONST |
SEGMENT |
|
|
адрес RTTI данных |
.weak |
_ZTV2xx |
|
|||||
|
# define __cdecl |
__attribute__((cdecl)) |
|
??_7xx@@6B@ |
DD ??_R4xx@@6B@ |
.section |
.rodata |
|||||||||||||
|
|
|
|
|
|
|||||||||||||||
|
# define __stdcall __attribute__((stdcall)) |
|
|
|
DD ??_Exx@@UAEPAXI@Z |
|
|
|
ZTV2xx: |
адрес RTTI данных |
||||||||||
|
# define __fastcall __attribute__((fastcall)) |
|
CONST |
ENDS |
|
|
|
|
|
|||||||||||
|
|
|
|
|
адрес первого |
.long |
0 |
|
||||||||||||
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
SEGMENT |
|
|
|
.long |
_ZTI2xx |
|
||||
|
|
|
|
|
традиционное соглашение |
|
|
|
|
|
виртуального |
|
||||||||
|
struct xy { |
|
|
|
|
|
??0xx@@QAE@XZ |
|
|
.long |
_ZN2xxD1Ev |
|||||||||
|
|
|
|
о вызовах C++ (т.н. thiscall) |
|
|
|
|
метода |
|
|
|||||||||
|
int |
x, y; |
|
??0xx@@QAE@XZ PROC |
; xx::xx() |
|
|
|
.long |
_ZN2xxD0Ev |
||||||||||
|
в ECX передается this |
|
(здесь: деструктора) |
|||||||||||||||||
|
}; |
|
|
|
|
|
= ecx |
|
|
.text |
|
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
mov |
eax, ecx |
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.globl _ZN2xxC1Ev |
|
|||||
|
|
this |
|
|
|
|
|
|
|
|
mov |
DWORD PTR [eax], OFFSET ??_7xx@@6B@ |
|
|
||||||
|
class xx { |
|
|
|
|
|
|
|
|
|
_ZN2xxC1Ev: |
|
|
|||||||
|
void **vtable; |
|
|
|
|
|
|
|
|
|||||||||||
|
protected: |
|
|
|
void *RTTI; |
|
|
|
mov |
DWORD PTR [eax+4], - |
|
|
|
|
movl |
4(%esp), %eax |
||||
|
|
|
int m_v; |
|
|
|
|
ret |
0 |
|
|
|
|
|
||||||
|
int m_v; |
|
|
|
void (*)(...) |
|
|
|
|
инициализация указателя |
movl |
$_ZTV2xx+8, (%eax) |
||||||||
|
|
|
... |
|
|
|
|
??0xx@@QAE@XZ ENDP |
|
|||||||||||
|
public: |
|
|
|
|
... |
|
|
|
на таблицу виртуальных |
movl |
$-1, 4(%eax) |
||||||||
|
xx( void ) { m_v = -1; } |
|
|
|
|
PUBLIC |
??1xx@@UAE@XZ |
|
|
методов |
|
|
ret |
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
||||||||||
|
virtual ~xx( void ) {} |
|
|
|
|
??1xx@@UAE@XZ PROC |
; xx::~xx |
|
|
|
.globl _ZN2xxD1Ev |
|
||||||||
|
static long long __cdecl sumxy |
|
|
mov |
DWORD PTR [ecx], OFFSET ??_7xx@@6B@ |
|
|
|||||||||||||
|
|
|
|
_ZN2xxD1Ev: |
|
|
||||||||||||||
|
( struct xy ); |
|
|
|
|
|
|
ret |
0 |
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
movl |
4(%esp), %eax |
|||||||
|
struct xy __stdcall getxy |
|
|
|
|
??1xx@@UAE@XZ ENDP |
|
|
|
|
|
|||||||||
|
|
|
|
|
|
|
|
|
|
movl |
$_ZTV2xx+8, (%eax) |
|||||||||
|
( int ); |
|
|
|
|
|
|
|
|
|
|
В GCC this передается |
||||||||
|
|
|
|
|
|
|
|
|
|
|
ret |
|
|
|||||||
|
double __fastcall getsum |
|
|
|
|
|
|
|
|
как обычный аргумент |
|
|
|
|||||||
|
( int, double, int, double ); |
|
|
|
|
|
|
в стеке |
|
|
|
|
|
|||||||
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2. Неэкземплярный метод, передача структуры в качестве аргумента, соглашение о вызовах cdecl |
|
|
|
|
|
|
|
|||||||||||||
|
long long __cdecl xx::sumxy( struct xy S ) |
|
PUBLIC |
?sumxy@xx@@SA_JUxy@@@Z |
|
|
|
.globl _ZN2xx5sumxyE2xy |
||||||||||||
|
{ |
|
|
|
|
|
|
|
|
_S$ = 8 |
|
|
|
; size = 8 |
|
_ZN2xx5sumxyE2xy: |
|
|||
|
return (long long)S.x + S.y; |
|
?sumxy@xx@@SA_JUxy@@@Z PROC |
|
|
|
|
pushl |
%ebx |
|
||||||||||
|
} |
|
|
|
|
|
|
|
|
|
mov |
eax, DWORD PTR _S$[esp] |
|
|
|
movl |
12(%esp), %eax |
|||
|
При передаче структуры в качестве аргумента |
|
|
cdq |
|
|
|
|
|
|
movl |
8(%esp), %ecx |
||||||||
|
вызывающий код создает в стеке на месте нужного |
|
|
mov |
ecx, eax |
|
|
|
|
movl |
|
|
||||||||
|
аргумента временную копию структуры. В C++ это |
|
|
mov |
eax, DWORD PTR _S$[esp- |
|
|
|
movl |
|
|
|||||||||
|
может приводить к неявному вызову конструкторов |
|
|
push |
esi |
|
esp |
→ retaddr |
sarl |
|
|
|||||||||
|
копирования и деструкторов после выхода из |
|
|
mov |
esi, edx |
sarl |
|
|
||||||||||||
|
|
|
+4 |
→ xy.x |
|
|
|
|
||||||||||||
|
вызванной функции (отдельный вопрос связан с тем — |
|
|
cdq |
|
|
|
|
addl |
|
|
|||||||||
|
|
|
|
|
+8 |
→ xy.y |
|
|
|
|
||||||||||
|
кто и когда должен вызывать деструкторы и какие |
|
|
add |
ecx, eax |
|
|
adcl |
|
|
||||||||||
|
|
|
|
... |
|
|
|
|
||||||||||||
|
именно). |
|
|
|
|
|
|
|
|
|
adc |
esi, edx |
|
|
|
popl |
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
mov |
edx, esi |
|
|
|
|
ret |
esp |
→ ebx |
|
|
|
|
|
|
|
|
|
|
|
|
mov |
eax, ecx |
|
|
|
|
|
+4 |
→ retaddr |
|
|
|
|
|
|
|
|
|
|
|
|
pop |
esi |
|
|
|
|
|
|
+8 |
→ xy.x |
|
|
|
|
|
|
|
|
|
|
|
ret |
0 |
|
|
|
|
|
|
+12 |
→ xy.y |
|
|
|
|
|
|
|
|
|
|
?sumxy@xx@@SA_JUxy@@@Z ENDP |
|
|
|
|
|
|
... |

3. Экземплярный метод, возвращение структуры в виде результата, соглашение о вызовах stdcall |
|
|
|
|
|
|
|
|||||||
|
struct xy __stdcall xx::getxy( int v ) |
|
PUBLIC |
?getxy@xx@@QAG?AUxy@@H@Z |
|
|
|
.globl _ZN2xx5getxyEi |
||||||
|
{ |
|
|
_this$ = 8 |
|
|
; size = 4 |
|
_ZN2xx5getxyEi: |
|||||
|
struct xy |
R; |
|
___$ReturnUdt$ = 12 |
|
; size = 4 |
|
|
|
movl |
8(%esp), %edx |
|||
|
|
|
|
_v$ = 16 |
|
|
; size = 4 |
|
|
|
movl |
4(%esp), %eax |
||
|
R.x = m_v; |
|
|
?getxy@xx@@QAG?AUxy@@H@Z PROC |
|
|
|
|
|
|
|
%edx |
||
|
R.y = v; |
|
|
|
mov |
eax, DWORD PTR _this$[esp-4] |
|
|
|
|
(%eax) |
|||
|
return R; |
|
|
|
mov |
ecx, DWORD PTR [eax+4] |
|
|
|
|
|
%edx |
||
|
} |
|
|
|
mov |
eax, DWORD PTR ___$ReturnUdt$[esp- |
|
|
|
4(%eax) |
||||
|
Память для возвращаемой структуры выделяет |
|
|
mov |
edx, DWORD PTR |
|
|
|
|
|
|
|
|
|
|
вызывающий код, предавая адрес выделенной |
|
mov |
DWORD PTR [eax], |
|
|
esp |
→ retaddr |
||||||
|
области в виде неявного аргумента функции. Таким |
|
mov |
DWORD PTR [eax+4], |
|
|
||||||||
|
образом данная функция имеет три аргумента — один |
|
ret |
12 |
|
|
|
+4 |
→ xy *p |
|
||||
|
явный (int v) и два неявных: this и указатель на |
?getxy@xx@@QAG?AUxy@@H@Z ENDP |
esp |
→ retaddr |
+8 |
→ xx *this |
||||||||
|
возвращаемую структуру. |
|
|
|
|
|
+12 |
→ int v |
|
|||||
|
|
|
|
|
|
+4 |
→ xx *this |
|
|
|
... |
|
||
|
Инструкция выхода из процедуры (ret 12) |
|
|
|
|
|
|
|
||||||
|
|
|
|
+8 |
→ xy *p |
|
|
|
|
|
||||
|
освобождает стек от переданных аргументов (3*4). |
|
|
|
|
|
|
|
|
|||||
|
|
|
|
+12 |
→ int v |
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|||
4. Экземплярный метод, соглашение о вызовах fastcall |
PUBLIC |
?getsum@xx@@QAINHNHN@Z |
|
... |
|
.globl _ZN2xx6getsumEidid |
||||||||
|
double __fastcall xx::getsum |
|
|
|
|
|
||||||||
|
( int a, double b, int c, double d ) |
|
EXTRN |
__fltused:DWORD |
|
|
|
|
_ZN2xx6getsumEidid: |
|||||
|
{ |
|
|
EXTRN |
__ftol2_sse:PROC |
|
|
|
|
|
|
subl |
$4, %esp |
|
|
double r = a+b+c+d; |
|
_a$ = -4 |
|
|
; size = 4 |
|
|
|
pushl |
%edx |
|||
|
m_v = (int)r; |
|
|
_b$ = 8 |
|
|
|
; size = 8 |
|
|
|
fildl |
(%esp) |
|
|
return r; |
|
|
_c$ = 16 |
|
|
; size |
|
|
|
faddl |
12(%esp) |
||
|
} |
|
|
_d$ = 20 |
|
|
; |
|
|
|
|
fnstcw |
6(%esp) |
|
|
В архитектуре IA-32 соглашение fastcall предполагает |
|
?getsum@xx@@QAINHNHN@Z PROC |
|
|
esp |
→ копия a |
|
movzwl |
6(%esp), %eax |
||||
|
использование двух регистров ECX и EDX для передачи |
; _this$ = ecx |
|
|
|
|
fildl |
20(%esp) |
||||||
|
|
|
|
+4 |
→ short cw1 |
|||||||||
|
первых двух аргументов целого (или приводимого к |
; _a$ = edx |
|
|
|
faddp |
%st, %st(1) |
|||||||
|
целому) типа. Для экземплярного метода первый |
|
push |
ecx |
|
|
+6 |
→ short cw0 |
movb |
$12, %ah |
||||
|
аргумент — неявный this (будет |
|
mov |
DWORD PTR _a$[esp+4], edx |
+8 |
→ retaddr |
|
faddl |
24(%esp) |
|||||
|
второй — int a (будет размещен в |
|
fild |
DWORD PTR _a$[esp+4] |
|
+12 |
→ double b |
movw |
%ax, 4(%esp) |
|||||
|
|
push |
esi |
|
|
+20 |
→ int c |
|
fldcw |
4(%esp) |
||||
|
аргументы должны быть размещены |
|
|
|
+24 |
→ double d |
||||||||
|
Интересный момент — инструкция |
|
mov |
esi, ecx |
|
|
|
... |
|
fistl |
4(%ecx) |
|||
|
|
fadd |
QWORD PTR _b$[esp+4] |
|
|
|
fldcw |
6(%esp) |
||||||
|
в double требует задания операнда |
|
|
edx |
: int a |
|
||||||||
|
|
fiadd |
DWORD PTR _c$[esp+4] |
|
|
addl |
$8, %esp |
|||||||
|
ссылки на память, а (согласно |
|
fadd |
QWORD PTR _d$[esp+4] |
|
ecx |
: xx *this |
ret |
$20 |
|||||
|
аргумент размещен в регистре EDX. |
|
fld |
ST(0) |
|
|
|
|
|
|
|
|
||
|
по сути размещают этот аргумент в |
|
|
|
|
|
|
|
|
|
||||
|
|
call |
__ftol2_sse |
|
|
|
|
|
|
|
|
|||
|
обращаются к его «локальной копии» |
|
mov |
DWORD PTR [esi+4], eax |
Регистр |
ECX не сохраняется при вызове вложенной |
||||||||
|
выделен жирным) |
ECX не является |
|
pop |
esi |
|
процедуры (_ftol2_sse), а указатель this (в ECX) нам |
|||||||
|
|
сохраняемым, |
|
pop |
ecx |
|
|
будет нужен после её вызова для сохранения |
||||||
|
|
это резервирование |
|
ret |
20 |
|
|
|
результата в this->m_v. |
|||||
|
|
места для EDX |
?getsum@xx@@QAINHNHN@Z ENDP |
|
Поэтому this из ECX копируют в ESI (который является |
сохраняемым) и, соответственно, сохраняют ESI в стеке
до его использования и восстанавливают после. (выделено курсивом)

5. Функция, не являющаяся методом, соглашение cdecl double cpptest( int y )10
{
xx t;
return (double)t.getsum( (int)t.sumxy( t.getxy(y) ), 0.0, -1,
(double)y
);
}
#ifdef __cplusplus extern "C" { #endif
double ctest( int y )
{
return cpptest( y );
}
#ifdef __cplusplus
}
#endif
По логике приведенной процедуры должны быть выполнены следующие действия:
-выделено пространство для xx t и выполнен конструктор xx::xx()
-выделено пространство для структуры xy, возвращаемой методом getxy; должен быть выполнен (неявный) конструктор xy::xy().
-выполнен экземплярный метод getxy (__stdcall).
-выполнен неэкземплярный метод sumxy (__cdecl).
-выполнен экземплярный метод getsum (__fastcall) с приведением результата (long) к типу double.
-выполнен (неявный) деструктор xy::~xy();
освобождено пространство, занимаемое временной структурой xy.
- выполнен деструктор xx::~xx(); освобождено пространство, занимаемое xx t.
В зависимости от режима оптимизации компиляторы могу пропускать некоторые шаги (например, вызов неявных конструкторов и деструкторов структуры), подставлять текст коротких функций, вместо их вызова (например, деструктор xx::~xx() может быть
подставлен и элиминирован) и т.п.
|
|
|
PUBLIC ?cpptest@@YANH@Z |
|
|
_t$ = -16 |
|
; size = 8 |
$T2647 = -8 |
|
; size = 8 |
_y$ = 8 |
|
; size = 4 |
?cpptest@@YANH@Z PROC |
|
|
sub |
esp, 16 |
|
lea |
ecx, DWORD PTR _t$[esp+16] |
|
call |
??0xx@@QAE@XZ |
; xx::xx |
mov |
eax, DWORD PTR _y$[esp+12] |
|
push |
eax |
|
lea |
ecx, DWORD PTR $T2647[esp+20] |
|
push |
ecx |
|
lea |
edx, DWORD PTR _t$[esp+24] |
|
push |
edx |
|
call |
?getxy@xx@@QAG?AUxy@@H@Z ; xx::getxy |
|
fild |
DWORD PTR _y$[esp+12] |
|
mov |
ecx, DWORD PTR [eax+4] |
|
mov |
edx, DWORD PTR [eax] |
|
sub |
esp, 8 |
|
fstp |
QWORD PTR [esp] |
|
push |
-1 |
|
fldz |
|
|
sub |
esp, 8 |
|
fstp |
QWORD PTR [esp] |
|
push |
ecx |
|
push |
edx |
|
call |
?sumxy@xx@@SA_JUxy@@@Z ; xx::sumxy |
|
add |
esp, 8 |
|
mov |
edx, eax |
|
lea |
ecx, DWORD PTR _t$[esp+36] |
|
call |
?getsum@xx@@QAINHNHN@Z ; xx::getsum |
|
add |
esp, 16 |
|
ret |
0 |
|
?cpptest@@YANH@Z ENDP |
|
|
PUBLIC _ctest |
|
|
_y$ = 8 |
|
; size = 4 |
_ctest PROC |
|
|
jmp |
?cpptest@@YANH@Z |
; cpptest |
_ctest ENDP |
|
|
.globl _Z7cpptesti _Z7cpptesti:
pushl %esi pushl %ebx subl $68, %esp
movl |
80(%esp), %esi |
leal |
56(%esp), %ebx |
movl |
%ebx, (%esp) |
call |
_ZN2xxC1Ev |
leal |
40(%esp), %eax |
movl |
%ebx, 4(%esp) |
movl |
%esi, 8(%esp) |
movl |
%eax, (%esp) |
call |
_ZN2xx5getxyEi |
subl |
$12, %esp |
movl |
40(%esp), %eax |
movl |
44(%esp), %edx |
movl |
%eax, (%esp) |
movl |
%edx, 4(%esp) |
call |
_ZN2xx5sumxyE2xy |
movl |
%ebx, %ecx |
pushl |
%esi |
fildl |
(%esp) |
addl |
$4, %esp |
movl |
%eax, %edx |
fstpl |
12(%esp) |
fldz |
|
fstpl |
(%esp) |
movl |
$-1, 8(%esp) |
call |
_ZN2xx6getsumEidid |
subl |
$20, %esp |
fstpl |
32(%esp) |
movl |
%ebx, (%esp) |
call |
_ZN2xxD1Ev |
fldl |
32(%esp) |
addl |
$68, %esp |
popl |
%ebx |
popl |
%esi |
ret |
|
.globl ctest |
|
ctest: |
|
jmp |
_Z7cpptesti |