最近,我一直只是在尝试学习一些汇编程序,我认为Nasm是一个不错的选择,因为我更习惯于它的intel_syntax。无论如何,在故意尝试找到一些用于64位Windows的示例程序之后,我发现了this帖子,并尝试使用第二个答案提供的代码。唯一的问题是该代码是针对x86 Windows的,而不是我的目标平台。因此,我试图编写了用于64位Windows的程序(请注意单词试图)。我对Assembly很陌生,因此我的代码很可能是不正确的,如果有人指出此类错误,我将不胜感激。
但是,我遇到的问题是链接。出于某种原因,当我尝试链接目标文件时, gcc 链接器无法解析外部符号(即winapi函数),而且我无法弄清楚为什么这样做。
这是我的代码(我在每一行中都加了注释,以便我可以尝试了解程序在做什么,但是请随时编辑此帖子,并在错误的地方进行任何更改)。
section .text ;Section of the src file that contains the actual runtime code
global WinMain@16 ;Makes the address WinMain global. @16 signifies 16 bytes of parameters
extern _GetStdHandle@4 ;Assures compiler of an external definition of the declared function 'GetStdHandle()'
extern _WriteFile@36 ;Assures compiler of an external definition of the declared function 'WriteFile()'
extern _ExitProcess@4 ;Assures compiler of an external definition of the declared function 'ExitProcess()'
WinMain@16: ;Label marking the entry-point of the program (Windows expects 'WinMain' unless explicitly specified)
mov rbp, rsp ;Move Stack Pointer value equal to Base Pointer
sub rsp, 4 ;Move Stack Pointer back (i.e. subtract) 4 bytes to store DWORD '-11' (defined by 'STD_OUTPUT_HANDLE')
push -11 ;Push '-11' into stack
call _GetStdHandle@4 ;Calls GetStdHandle(-11) since -11 has been pushed. @4 signifies 4 bytes of parameters
mov rbx, rax ;rax stores return value -> move that value to rbx
push 0 ;Push 0 (NULL) onto the stack (This is the last argument in the function)
lea rax, [rbp - 4] ;Store address of DWORD in rax register (4 byte value, 8 byte pointer)
push rax ;Push address of DWORD as the next parameter
push (msg_end - msg) ;Push number of bytes to write (3rd parameter)
push msg ;Push pointer to constant data bytes (2nd parameter)
push rbx ;Push value stored in 'rbx' (The HANDLE) into the 1st parameter
call _WriteFile@36 ;Calls WriteFile(hStdOut, msg, msg_len, bytes_written, NULL). @36 signifies 36 bytes of parameters
push 0 ;Push 0 onto the stack (parameter)
call _ExitProcess@4 ;Calls ExitProcess(0) and ends the program. @4 signifies 4 bytes of parameters
; ---- << Nothing gets called a beyond this line >> ---- ;
hlt ;I have no clue why you need to halt here
msg: ;Label marking the start of the message
db "Hey world", 10 ;Actual data, (db = define bytes). "Hey world" and 10 (new-line character)
msg_end: ;Label marking the end of the message
要进行编译,请运行以下命令
nasm -f win64 Main.asm -o Main.bin
链接,我运行它并获得以下输出...
gcc -o Hello.exe Main.o
bin/Main.o:src/Main.asm:(.text+0xa): undefined reference to `_GetStdHandle@4'
bin/Main.o:src/Main.asm:(.text+0x21): undefined reference to `_WriteFile@36'
bin/Main.o:src/Main.asm:(.text+0x28): undefined reference to `_ExitProcess@4'
collect2.exe: error: ld returned 1 exit status
如您所见,它无法链接到外部函数,有趣的是,当我尝试调用“ puts”之类的“ c”函数时,它工作得很好
无论如何,如果您能在这里帮助我并指出我的代码中的任何错误,我将不胜感激。