Вызов FormatMessageA из 64-битной программы на ассемблере
Я несколько дней работал над подпрограммой ассемблера для вызова функции Windows API FormatMessageA, и я думаю, что у меня должно быть какое-то систематическое недопонимание. Мой распорядок показан ниже. Я проследил это в режиме отладки и знаю, что в момент вызова функции: rcx имеет шестнадцатеричное значение 1B00, которое является указанными мной значениями флагов (dwFlags); rdx имеет шестнадцатеричное значение 33, которое является фиктивным начальным значением дескриптора, которое я подключил, чтобы вызвать ошибку (lpSource); r8 имеет 6, это номер сообщения об ошибке, возвращенный GetLastError, что соответствует ERROR_INVALID_HANDLE (dwMessageId); r9 имеет 0 для языка по умолчанию (dwLanguageId); rsp+32 имеет адрес msgptrp, который является моей областью для получения адреса сообщения об ошибке, выделенного вызываемой функцией (lpBuffer); rsp+40 имеет шестнадцатеричный 28 или десятичный 40,это минимальное количество символов, которое я произвольно указал для сообщения об ошибке (nSize); а rsp+48 имеет адрес argmntsp, который, согласно документации, следует игнорировать с указанными мной флагами (* Аргументы).
Если есть проблема, и, очевидно, она есть, поскольку rax возвращается как ноль, я подозреваю, что это связано с lpBuffer, который, как сказано в документации, имеет тип данных LPTSTR, каким бы он ни был. Иногда мне хочется крикнуть: "Хорошо, это то, что есть в терминах C++, но что это на самом деле? Я надеюсь, что кто-то легко заметит, где я сбежал с рельсов, потому что я в своем уме на этом, и это то, над чем мне нужно работать, чтобы эффективно проверять ошибки в моих будущих начинаниях.
goterr PROC
;
.data
; flag values used:
; hex 00000100 FORMAT_MESSAGE_ALLOCATE_BUFFER
; hex 00000200 FORMAT_MESSAGE_IGNORE_INSERTS
; hex 00000800 FORMAT_MESSAGE_FROM_HMODULE
; hex 00001000 FORMAT_MESSAGE_FROM_SYSTEM
flagsp dd 00001B00h ; those flags combined
saveinitp dq ?
bmaskp dq 0fffffffffffffff0h
savshadp dq ?
msgptrp dq ?
handlep dd ?
argmntsp dd ?
;
.code
mov saveinitp, rsp ; save initial contents of stack pointer in this proc
sub rsp, 56 ; shadow space (max of 7 parameters * 8)
and rsp, bmaskp ; make sure it's 16 byte aligned
mov savshadp, rsp ; save address of aligned shadow area for this proc
;
mov handlep, ecx ; save passed I/O handle value locally
;
call GetLastError ; get the specific error
;
mov rsp, savshadp ; shadow area for this proc
mov ecx, flagsp ; flags for Windows error routine
mov edx, handlep ; handle passed from caller
mov r8d, eax ; msg id from GetLastError in low order dword
mov r9, 0 ; default language id
lea rax, msgptrp ; pointer to receive address of msg buffer
mov [rsp+32], rax ; put it on the stack
mov rax, 40 ; set lower doubleword to minimum size for msg buffer
mov [rsp+40], rax ; put it on the stack
lea rax, argmntsp ; variable arguments parameter (not used)
mov [rsp+48], rax ; put it on the stack
call FormatMessageA ; if rax eq 0 the called failed, otherwise rax is no chars.
mov rsp, saveinitp ; restore initial SP for this proc
ret
goterr ENDP