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

Листинг 8 пример вызова API-функции с пятью параметрами по соглашению x86-64

Смещение пятого аргумента относительно верхушки стека требует пояснений. Почему оно равно 20h? Ведь адрес возврата занимает только 8 байт. Какая су… сущность съела все остальные? Оказывается, они "резервируются" для первых четырех аргументов, переданных через регистры. "Зарезервированные" ячейки содержат неинициализированный мусор и по-буржуйски называются "spill", что переводится как "затычка" или "потеря".

Вот минимум знаний, необходимых для выживания в мире 64-битной Windows при программировании на ассемблере. Остается разобрать самую малость. Как эти самые 64-бита заполучить?! Для перевода FASM'а в x86-64 режим достаточно указать директиву "use64" и дальше шпрехать как обычно.

Ниже идет пример простейшей x86-64 программы, которая не делает ничего, только возвращает в регистре RAX значение "ноль".

 

; сообщаем FASM'у, что мы хотим программировать на x86-64