Насколько я понимаю, лучший способ сделать что-то на ассемблере x86-64 - это не программировать что-то самостоятельно. Вместо этого попросите Windows сделать это за вас. Например, открыть новую консоль или напечатать текст в окне консоли. Но вы не можете вызывать системные вызовы Windows напрямую, так как они могут быть изменены по щелчку пальцев Microsoft. Итак, вы вызываете Windows API через call-команды.
Итак, я хочу иметь возможность программировать полные приложения в сборке x86-64 в Windows 10, но мне трудно найти информацию о Windows API. В частности, какую информацию/данные/числа передавать в RCX, RDX, R8 и R9 перед вызовом функции Windows API? Например, программа Hello World, которую я нашел где-то в Интернете, использует как «GetStdHandle», так и «WriteConsoleA». Я понимаю, что они делают, но я не знаю, что означают все числа и манипулирование регистрами или как это влияет на Windows API. Вот код:
extern GetStdHandle
extern WriteConsoleA
section .data
msg: db "HelloWorld"
msglen: equ $-msg
section .bss
section .text
start:
mov ECX, -11
call GetStdHandle
mov RCX, RAX
mov RDX, msg
mov R8, msglen
lea R9, [RSP-16]
call WriteConsoleA
mov EAX, 0
ret
Это было скомпилировано с помощью NASM и связано с Golink. Вот make-файл:
{NasmPath} -f win64 HelloWorld.asm
{GoLinkPath} HelloWorld.obj /console kernel32.dll
Для пояснения: я не запускал {NasmPath} или {GoLinkPath} через консоль, я просто отредактировал его, потому что в фактическом пути есть мое имя.
TLDR: где я могу найти информацию о том, какие данные следует передавать через регистры RCX, RDX, R8 и R9 в функции Windows API?
Каждый API, описанный для C, можно найти здесь. Например GetStdHandle
: learn.microsoft.com/en-us/windows/console/console-functions . Вы можете искать многие другие вызовы API там.
Соглашения о вызовах Windows x64 задокументированы в Microsoft Docs.
Вызов GetStdHandle
очень прост: он передает STD_OUTPUT_HANDLE
(-11) в качестве первого параметра, который использует ECX; возвращаемое значение находится в RAX.
Вызов WriteConsoleA
немного сложнее. Технически функция принимает 5 параметров, последний из которых зарезервирован, но код передает только четыре.
Имейте в виду, что написать полностью «правильную» сборку Windows x64 довольно сложно из-за необходимой информации для раскручивания исключений. Есть некоторые макросы MASM, но не знаю о NASM.
@AlienAbove Вы можете писать программы для Windows на ассемблере без обработки исключений, включая графические приложения.
Я ожидаю, что вызовы перезапишут адрес возврата, поэтому он вылетит на ret
внизу, поскольку эта программа не может зарезервировать 32 байта теневого пространства перед вызовами. Это важная часть соглашения о вызовах, которому этот код не следует. Он также передает указатель на [RSP-16]
, который находится внутри кадра стека вызываемого объекта.
Первое, что вам нужно понять, это соглашение о вызовах Win64. Это говорит о том, какие регистры (или стек) используются для каких параметров. Вы можете найти информацию о соглашении о вызовах Win64 здесь: learn.microsoft.com/en-us/cpp/build/… здесь: en.wikipedia.org/wiki/… . База не заключается в том, что вы просто находите, что API нужно передать для каждого параметра, и кодируете это в соответствии с соглашением о вызовах.