nasm 彙編輸出 helloworld-windows 32位與64位測試通過
阿新 • • 發佈:2018-12-02
使用nasm彙編,然後用visual studio的link連線成exe
選安裝nasm與visual studio
// hello.asm
STD_OUTPUT_HANDLE equ -11
NULL equ 0
global GobleyGook
extern [email protected], [email protected], [email protected]
section .data
msg db "Hello World!", 13, 10, 0
msg.len equ $ - msg
section .bss
dummy resd 1
section .text
GobleyGook:
push STD_OUTPUT_HANDLE
call [email protected]
push NULL
push dummy
push msg.len
push msg
push eax
call [email protected]
push NULL
call [email protected]
開啟x86本機命令提示符 編譯 nasm -f win32 hello.asm -o hello.obj 連線 link /subsystem:console /nodefaultlib /entry:GobleyGook hello.obj kernel32.lib 執行 hello.exe
【彙編說明】
hello.asm中的
extern是宣告呼叫的函式,函式名在kernel32.lib庫中
call前面的幾個push是把call 這個函式需要的引數入棧,第一個push的是函式引數列表的最後一個,倒序
/entry:GobleyGook 是指定入口地址
[email protected]是獲取std控制代碼,也就是命令提示符控制代碼,返回的結果在eax暫存器,所以[email protected]的第一個引數就是最後一個push eax
開啟 x64本機命令提示符 或者 x86本機命令提示符 匯出 kernel32.lib 中的符號,也就是函式名 到檔案 dumpbin /EXPORTS kernel32.lib >kernel32.txt 雖然都叫 kernel32.lib,但在x86與x64下不是同一個檔案,所以 符號 (函式名稱) 不同,連結會報找不到符號 匯出的檔案內有kernel32.lib的路徑,是編譯時使用的庫檔案 x86本機命令提示符, 執行時使用的是 system32 目錄下 x64本機命令提示符, 執行時使用的是 syswow64 目錄下
以下是的64位
// hello.asm 64位
STD_OUTPUT_HANDLE equ -11
NULL equ 0
global GobleyGook
extern ExitProcess, GetStdHandle, WriteConsoleA
section .data
msg db "Hello World!", 13, 10, 0
msg.len equ $ - msg
section .bss
dummy resq 1
section .text
GobleyGook:
mov ecx,0fffffff5h
call GetStdHandle
mov r9,dummy
mov r8d,0dh
mov rdx,msg
mov rcx,rax
call WriteConsoleA
push NULL
call ExitProcess
開啟x64本機命令提示符
nasm -f win64 hello.asm -o hello.obj
link /subsystem:console /nodefaultlib /entry:GobleyGook /machine:X64 hello.obj kernel32.lib
hello.exe
【64位彙編說明】
64位函式呼叫沒有用push,因為1.push不能直接64位, 2.push不能呼叫成功
windows的引數傳遞 (Parameter Passing, 函式引數列表從左到右,rcx,rdx,r8,r9的暫存器順序)
GetStdHandle函式的結果在rax暫存器, mov rcx,rax就是把結果放入rcx作為WriteConsoleA的第一個引數
上面的64彙編是看的vs的反彙編程式碼所啟發,f9加斷點,f5執行到斷點後,右鍵–轉到反彙編
#include <Windows.h>
using namespace std;
int main()
{
char* str = "Hello World!";
DWORD byteswritten;
HANDLE hwnd;
hwnd = GetStdHandle(STD_OUTPUT_HANDLE);
WriteConsole(hwnd, "Hello World!", 13, &byteswritten, NULL); //斷點行
return 0;
}