Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #83, НОЯБРЬ 2005 г.

64-битный привет

Крис Касперски ака мыщъх

Хакер, номер #083, стр. 083-118-4


[обзор x86-64]

За подробным описанием x86-64-архитектуры лучше всего обратиться к фирменной документации AMD64 Technology - AMD64 Architecture Programmer's Manual Volume 1:Application Programming (http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/24593.pdf). Мы же ограничимся только беглым обзором основных нововведений.

Наконец-то AMD сжалилась над нами и подарила программистам то, что все так долго ждали. К семи регистрам общего назначения (восьми - с учетом ESP) добавилось еще восемь, в результате чего их общее количество достигло 15 (16) штук.

Старые регистры, расширенные до 64-бит, получили имена RAX, RBX, RCX, RDX, RBP, RSI, RDI, RSP, RIP и RFLAGS. Новые регистры остались безымянными и просто пронумерованы от R8 до R15. Для обращения к младшим 8-, 16- и 32-битам новых регистров можно использовать суффиксы b, w и d. Например, R9 - это 64-разряный регистр, R9b - его младший байт (по аналогии с AL), а R9w - младшее слово (тоже самое, что AX в EAX). Прямых наследников AH к сожалению не наблюдается и для манипуляции со средней частью регистров приходится извращаться со сдвигами и математическими операциями.

Регистр, указатель команд RIP, теперь адресуется точно так же, как и все остальные регистры общего назначения. Программисты, заставшие живую PDP-11 (или ее отечественный клон - Электронику БК или УКНЦ), только презрительно хмыкнут - наконец-то до разработчиков стали доходить очевидные истины, которые на всех нормальных платформах были реализованы еще неизвестно когда.

Возьмем простейший пример: загрузим в регистр AL опкод следующей машинной команды. На x86 приходится поступать так.

[загрузка опкода следующей машинной команды в классическом x86]

call $ + 5 ; запихнуть в стек адрес следующей команды и передать на нее управление

pop ebx ; вытолкнуть из стека адрес возврата

add ebx, 6 ; скорректировать адрес на размер команд pop/add/mov

mov al, [ebx] ; теперь AL содержит опкод команды NOP

NOP ; команда, чей опкод мы хотим загрузить в AL

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

А теперь перепишем тот же самый пример на x86-64.

[загрузка опкода следующей машинной команды на x86-64]

mov al,[rip] ; загружаем опкод следующей машинной команды

NOP ; команда, чем опкод мы хотим загрузить в AL

Красота! Только следует помнить, что RIP всегда указывает на следующую, а отнюдь не текущую инструкцию! К сожалению, ни Jx RIP, ни CALL RIP не работают. Таких команд в лексиконе x86-64 просто нет.

Но это еще что! Исчезла абсолютная адресация! Если нам надо изменить содержимое ячейки памяти по конкретному адресу, на x86 мы поступаем приблизительно так:

Назад на стр. 083-118-3  Содержание  Вперед на стр. 083-118-5