If you don’t know how to write code in assembler, first write the code in Delphi, see what code the compiler generates (put a breakpoint in the function and when you reach it, open the disassembler window Ctrl+Alt+D ), take it as a basis and improve .
Here for this Delphi code:
procedure Crash; var VOldPrivilege: Boolean; begin RtlAdjustPrivilege(20, True, False, VOldPrivilege); RtlSetProcessIsCritical(1, nil, 0); ExitProcess(1); end;
when compiling in 64-bit mode, the following assembly code is generated:
push rbp sub rsp,$30 mov rbp,rsp mov ecx,$00000014 mov dl,$01 xor r8,r8 lea r9,[rbp+$2f] call RtlAdjustPrivilege mov ecx,$00000001 xor edx,edx xor r8,r8 call RtlSetProcessIsCritical mov ecx,$00000001 call ExitProcess lea rsp,[rbp+$30] pop rbp ret
But such a code for 32-bit mode, you can compare with yours:
push ebp mov ebp,esp push ecx lea eax,[ebp-$01] push eax push $00 push $01 push $14 call RtlAdjustPrivilege push $00 push $00 push $01 call RtlSetProcessIsCritical push $01 call ExitProcess pop ecx pop ebp ret
The difference between the code for different platforms is that for x32, the stdcall call stdcall (parameters are passed through the stack), and in x64, fastcall (the first 4 parameters are passed through registers, the rest through the stack).
When developing calling conventions for the x86-64 architecture, they decided to put an end to the existence of various options for calling functions. In Win32, there were a number of calling conventions: stdcall, cdecl, fastcall, thiscall, and so on. In Win64, there is only one native calling convention. Modifiers like __cdecl are ignored by the compiler. I think everyone will agree in the nobility of such a sharp reduction in the number of agreements.
The x86-64 calling convention is similar to the fastcall agreement in x86. In the x64 agreement, the first four integer arguments (from left to right) are transmitted in 64-bit registers chosen specifically for this purpose:
RCX: 1st integer argument
RDX: 2nd integer argument
R8: 3rd integer argument
R9: 4th integer argument
The remaining integer arguments are passed through the stack. The “this” pointer is considered an integer argument, so it is always placed in the RCX register. If floating-point values ​​are transmitted, the first four of them are transmitted in the XMM0-XMM3 registers, and the subsequent ones via the stack.
Quote from here: https://habrahabr.ru/company/intel/blog/94340/