1. 程式人生 > >nasm 彙編輸出 helloworld-windows 32位與64位測試通過

nasm 彙編輸出 helloworld-windows 32位與64位測試通過

使用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;
}