64-битный привет Крис Касперски ака мыщъх Хакер, номер #083, стр. 083-118-5 dec byte ptr [666h] ; уменьшить содержимое байта по адресу 666h на единицу Под x86-64 транслятор выдает ошибку ассемблирования, вынуждая нас прибегать к фиктивному базированию: xor r9, r9 ; обнулить регистр r9 dec byte ptr [r9+666h] ; уменьшить содержимое байта по адресу 0+666h на единицу Есть и другие отличия от x86, но они не столь принципиальны. Важно то, что в режиме совместимости с x86 (Legacy Mode) ни 64-битные регистры, ни новые методы адресации недоступны! Никакими средствами (включая черную и белую магию) дотянуться до них нельзя и прежде чем что-то сделать, необходимо перевести процессор в длинный режим (long mode), который делиться на два подрежима: режим совместимости с x86 (compatibility mode) и 64-битный режим (64-bit mode). Режим совместимости предусмотрен только для того, чтобы 64-разрядная операционная система могла выполнять старые 32-битные приложения. Никакие 64-битные регистры здесь и не ночевали! Реальная 64-битность обитает только в 64-bit long mode, о котором мы и будем говорить! [hello world на x86-64] Программирование под 64-битную версию Windows мало чем отличается от традиционного, только все операнды и адреса по умолчанию 64-разрядные, а параметры API-функций передаются большей частью через регистры, а не через стек. Первые четыре аргумента всех API-функций передаются в регистрах RCX, RDX, R8 и R9 (регистры перечислены в порядке следования аргументов, крайний левый аргумент помещается в RCX). А уж остальные параметры кладутся в стек. Все это называется x86-64 fast calling conversion (соглашение о быстрой передаче параметров для x86-64), подробное описание которой можно найти в статье The history of calling conventions, part 5 amd64 (http://blogs.msdn.com/oldnewthing/archive/2004/01/14/58579.aspx). Также советую заглянуть на страничку бесплатного компилятора Free PASCAL и поднять документацию по способам вызова API: http://www.freepascal.org/wiki/index.php/Win64/AMD64_API. В частности, вызов функции с пятью аргументами API_func(1,2,3,4,5) выглядит так: mov dword ptr [rsp+20h], 5 ; кладем на стек пятый слева аргумент mov r9d, 4 ; передаем четвертый слева аргумент mov r8d, 3 ; передаем третий слева аргумент mov edx, 2 ; передаем второй слева аргумент mov ecx, 1 ; передаем первый слева аргумент call API_func Смещение пятого аргумента относительно верхушки стека требует пояснений. Почему оно равно 20h? Ведь адрес возврата занимает только 8 байт. Какая су… сущность съела все остальные? Оказывается, они резервируются для первых четырех аргументов, переданных через регистры. Зарезервированные ячейки содержат неинициализированный мусор и по-буржуйски называются spill, что переводится как затычка или потеря. Вот минимум знаний, необходимых для выживания в мире 64-битной Windows при программировании на ассемблере. Остается разобрать самую малость: как эти самые 64-бита заполучить?! Для перевода FASM'а в x86-64 режим достаточно указать директиву use64 и дальше кодить как обычно. |