Академический Документы
Профессиональный Документы
Культура Документы
Reverse Engineering
Reverse Engineering
1 Образцы кода 1
4 Java 638
7 Инструменты 768
10 Прочее 973
12 Сообщества 990
Послесловие 992
Приложение 994
Глоссарий 1028
iii
ОГЛАВЛЕНИЕ
Оглавление
1 Образцы кода 1
1.1 Метод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Некоторые базовые понятия . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2.1 Краткое введение в CPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2.2 Представление чисел . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Пустая функция . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3.4 Пустые функции на практике . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.4 Возврат значения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.4.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.4.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.4.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.4.4 На практике . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.5 Hello, world! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.5.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.5.2 x86-64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.5.3 GCC — ещё кое-что . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.5.4 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.5.5 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.5.6 Вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.5.7 Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.6 Пролог и эпилог функций . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.6.1 Рекурсия . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.7 Стек . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.7.1 Почему стек растет в обратную сторону? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.7.2 Для чего используется стек? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.7.3 Разметка типичного стека . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
1.7.4 Мусор в стеке . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
1.7.5 Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
1.8 printf() с несколькими аргументами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
1.8.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
1.8.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
1.8.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
1.8.4 Вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
1.8.5 Кстати . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
1.9 scanf() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
1.9.1 Простой пример . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
1.9.2 Глобальные переменные . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
1.9.3 Проверка результата scanf() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
1.9.4 Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
1.10 Доступ к переданным аргументам . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
1.10.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
1.10.2 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
1.10.3 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
1.10.4 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
1.11 Ещё о возвращаемых результатах . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
1.11.1 Попытка использовать результат функции возвращающей void . . . . . . . . . . . . 107
1.11.2 Что если не использовать результат функции? . . . . . . . . . . . . . . . . . . . . . . . 108
1.11.3 Возврат структуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
1.12 Указатели . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
1.13 Оператор GOTO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
iv
ОГЛАВЛЕНИЕ
1.13.1 Мертвый код . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
1.13.2 Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
1.14 Условные переходы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
1.14.1 Простой пример . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
1.14.2 Вычисление абсолютной величины . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
1.14.3 Тернарный условный оператор . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
1.14.4 Поиск минимального и максимального значения . . . . . . . . . . . . . . . . . . . . . . 136
1.14.5 Вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
1.14.6 Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
1.15 switch()/case/default . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
1.15.1 Если вариантов мало . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
1.15.2 И если много . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
1.15.3 Когда много case в одном блоке . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
1.15.4 Fall-through . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
1.15.5 Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
1.16 Циклы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
1.16.1 Простой пример . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
1.16.2 Функция копирования блоков памяти . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
1.16.3 Проверка условия . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
1.16.4 Вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
1.16.5 Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
1.17 Еще кое-что о строках . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
1.17.1 strlen() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
1.18 Замена одних арифметических инструкций на другие . . . . . . . . . . . . . . . . . . . . . . 202
1.18.1 Умножение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
1.18.2 Деление . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
1.18.3 Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
1.19 Работа с FPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
1.19.1 IEEE 754 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
1.19.2 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
1.19.3 ARM, MIPS, x86/x64 SIMD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
1.19.4 Си/Си++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
1.19.5 Простой пример . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
1.19.6 Передача чисел с плавающей запятой в аргументах . . . . . . . . . . . . . . . . . . . 220
1.19.7 Пример со сравнением . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
1.19.8 Некоторые константы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
1.19.9 Копирование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
1.19.10 Стек, калькуляторы и обратная польская запись . . . . . . . . . . . . . . . . . . . . . 257
1.19.11 80 бит? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
1.19.12 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
1.19.13 Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
1.20 Массивы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
1.20.1 Простой пример . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
1.20.2 Переполнение буфера . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
1.20.3 Защита от переполнения буфера . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
1.20.4 Еще немного о массивах . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276
1.20.5 Массив указателей на строки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
1.20.6 Многомерные массивы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284
1.20.7 Набор строк как двухмерный массив . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
1.20.8 Вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
1.21 Кстати . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
1.21.1 Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
1.22 Работа с отдельными битами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
1.22.1 Проверка какого-либо бита . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
1.22.2 Установка и сброс отдельного бита . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
1.22.3 Сдвиги . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
1.22.4 Установка и сброс отдельного бита: пример с FPU1 . . . . . . . . . . . . . . . . . . . . 308
1.22.5 Подсчет выставленных бит . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312
1.22.6 Вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
1.22.7 Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
1.23 Линейный конгруэнтный генератор . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
1.23.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
1.23.2 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331
1 Floating-Point Unit
v
ОГЛАВЛЕНИЕ
1.23.3 32-bit ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332
1.23.4 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332
1.23.5 Версия этого примера для многопоточной среды . . . . . . . . . . . . . . . . . . . . . . 335
1.24 Структуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
1.24.1 MSVC: Пример SYSTEMTIME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
1.24.2 Выделяем место для структуры через malloc() . . . . . . . . . . . . . . . . . . . . . . . . 339
1.24.3 UNIX: struct tm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
1.24.4 Упаковка полей в структуре . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
1.24.5 Вложенные структуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
1.24.6 Работа с битовыми полями в структуре . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
1.24.7 Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
1.25 Объединения (union) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
1.25.1 Пример генератора случайных чисел . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
1.25.2 Вычисление машинного эпсилона . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
1.25.3 Быстрое вычисление квадратного корня . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373
1.26 Указатели на функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
1.26.1 MSVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375
1.26.2 GCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
1.26.3 Опасность указателей на ф-ции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
1.27 64-битные значения в 32-битной среде . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
1.27.1 Возврат 64-битного значения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
1.27.2 Передача аргументов, сложение, вычитание . . . . . . . . . . . . . . . . . . . . . . . . . 387
1.27.3 Умножение, деление . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
1.27.4 Сдвиг вправо . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
1.27.5 Конвертирование 32-битного значения в 64-битное . . . . . . . . . . . . . . . . . . . . 395
1.28 SIMD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396
1.28.1 Векторизация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
1.28.2 Реализация strlen() при помощи SIMD . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
1.29 64 бита . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410
1.29.1 x86-64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410
1.29.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
1.29.3 Числа с плавающей запятой . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
1.29.4 Критика 64-битной архитектуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
1.30 Работа с числами с плавающей запятой (SIMD) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418
1.30.1 Простой пример . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418
1.30.2 Передача чисел с плавающей запятой в аргументах . . . . . . . . . . . . . . . . . . . 425
1.30.3 Пример со сравнением . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426
1.30.4 Вычисление машинного эпсилона: x64 и SIMD . . . . . . . . . . . . . . . . . . . . . . . . 428
1.30.5 И снова пример генератора случайных чисел . . . . . . . . . . . . . . . . . . . . . . . . 429
1.30.6 Итог . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
1.31 Кое-что специфичное для ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
1.31.1 Знак номера (#) перед числом . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
1.31.2 Режимы адресации . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
1.31.3 Загрузка констант в регистр . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431
1.31.4 Релоки в ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433
1.32 Кое-что специфичное для MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434
1.32.1 Загрузка 32-битной константы в регистр . . . . . . . . . . . . . . . . . . . . . . . . . . . 434
1.32.2 Книги и прочие материалы о MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436
vi
ОГЛАВЛЕНИЕ
2.4.1 Проверка того, находится ли значение на границе 2n . . . . . . . . . . . . . . . . . . . . 448
2.4.2 Кирилличная кодировка KOI-8R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 448
2.5 И и ИЛИ как вычитание и сложение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
2.5.1 Текстовые строки в ПЗУ2 ZX Spectrum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
2.6 XOR (исключающее ИЛИ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
2.6.1 Бытовая речь . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
2.6.2 Шифрование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
2.6.3 RAID3 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
2.6.4 Алгоритм обмена значений при помощи исключающего ИЛИ . . . . . . . . . . . . . . 452
2.6.5 Список связанный при помощи XOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453
2.6.6 Хэширование Зобриста / табуляционное хэширование . . . . . . . . . . . . . . . . . . . 453
2.6.7 Кстати . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454
2.6.8 AND/OR/XOR как MOV . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454
2.7 Подсчет бит . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454
2.8 Endianness (порядок байт) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
2.8.1 Big-endian (от старшего к младшему) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
2.8.2 Little-endian (от младшего к старшему) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
2.8.3 Пример . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
2.8.4 Bi-endian (переключаемый порядок) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 456
2.8.5 Конвертирование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 456
2.9 Память . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 456
2.10 CPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
2.10.1 Предсказатели переходов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
2.10.2 Зависимости между данными . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
2.11 Хеш-функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
2.11.1 Как работает односторонняя функция? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
vii
ОГЛАВЛЕНИЕ
3.12 C99 restrict . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 506
3.13 Функция abs() без переходов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 509
3.13.1 Оптимизирующий GCC 4.9.1 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 509
3.13.2 Оптимизирующий GCC 4.9 ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510
3.14 Функции с переменным количеством аргументов . . . . . . . . . . . . . . . . . . . . . . . . . . 510
3.14.1 Вычисление среднего арифметического . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510
3.14.2 Случай с функцией vprintf() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514
3.14.3 Случай с Pin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515
3.14.4 Эксплуатация строки формата . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515
3.15 Обрезка строк . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 516
3.15.1 x64: Оптимизирующий MSVC 2013 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517
3.15.2 x64: Неоптимизирующий GCC 4.9.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519
3.15.3 x64: Оптимизирующий GCC 4.9.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 520
3.15.4 ARM64: Неоптимизирующий GCC (Linaro) 4.9 . . . . . . . . . . . . . . . . . . . . . . . . . 521
3.15.5 ARM64: Оптимизирующий GCC (Linaro) 4.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . 522
3.15.6 ARM: Оптимизирующий Keil 6/2013 (Режим ARM) . . . . . . . . . . . . . . . . . . . . . . 523
3.15.7 ARM: Оптимизирующий Keil 6/2013 (Режим Thumb) . . . . . . . . . . . . . . . . . . . . . 523
3.15.8 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 524
3.16 Функция toupper() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 525
3.16.1 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 526
3.16.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527
3.16.3 Используя битовые операции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 529
3.16.4 Итог . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 529
3.17 Обфускация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 530
3.17.1 Текстовые строки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 530
3.17.2 Исполняемый код . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 530
3.17.3 Виртуальная машина / псевдо-код . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532
3.17.4 Еще кое-что . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532
3.17.5 Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532
3.18 Си++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533
3.18.1 Классы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533
3.18.2 ostream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 549
3.18.3 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 550
3.18.4 STL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551
3.18.5 Память . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 584
3.19 Отрицательные индексы массивов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585
3.19.1 Адресация строки с конца . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585
3.19.2 Адресация некоторого блока с конца . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585
3.19.3 Массивы начинающиеся с 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 586
3.20 Больше об указателях . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588
3.20.1 Работа с адресами вместо указателей . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588
3.20.2 Передача значений как указателей; тэггированные объединения . . . . . . . . . . 591
3.20.3 Издевательство над указателями в ядре Windows . . . . . . . . . . . . . . . . . . . . . 591
3.20.4 Нулевые указатели . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596
3.20.5 Массив как аргумент функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 600
3.20.6 Указатель на функцию . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 600
3.20.7 Указатель как идентификатор объекта . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
3.21 Оптимизации циклов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 602
3.21.1 Странная оптимизация циклов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 602
3.21.2 Еще одна оптимизация циклов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 603
3.22 Еще о структурах . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 605
3.22.1 Иногда вместо массива можно использовать структуру в Си . . . . . . . . . . . . . . 605
3.22.2 Безразмерный массив в структуре Си . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 606
3.22.3 Версия структуры в Си . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 608
3.22.4 Файл с рекордами в игре «Block out» и примитивная сериализация . . . . . . . . . 609
3.23 memmove() и memcpy() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 614
3.23.1 Анти-отладочный прием . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 615
3.24 setjmp/longjmp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 615
3.25 Другие нездоровые хаки связанные со стеком . . . . . . . . . . . . . . . . . . . . . . . . . . . . 617
3.25.1 Доступ к аргументам и локальным переменным вызывающей ф-ции . . . . . . . . 617
3.25.2 Возврат строки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 619
3.26 OpenMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 621
3.26.1 MSVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 623
3.26.2 GCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 625
viii