編寫涉及系統特性的一些底層程序,特別是ShellCode,不可避免地要采用直接編寫匯編代碼的方式。
在目標平台為x86模式時,可以直接使用內聯匯編,這個很多人都比較熟悉了,也非常地方便。
但是當目標平台為x64時,微軟不再允許直接內聯匯編了,這給我們編程造成了一些不便。
怎么解決這個問題呢? 一種辦法是改用Intel的編譯器,它仍然支持內聯匯編。
另一種辦法還是用VS了,但是不能內聯,需要把匯編部分單獨寫到一個asm文件里,然后在其它源文件中引用。
我參考了一些網上的說明,在這里把過程寫詳細些,方便自己,也方便他人。
主要過程:
一、在asm文件中單獨編寫功能函數
比如要實現一個64位的加法函數,原型如下:
ULONG64 myAdd(ULONG64 u1,ULONG64 u2);
那么新建一個文件,寫入以下內容
.CODE myAdd PROC add rcx,rdx mov rax,rcx ret myAdd ENDP END
將以上內容保存為myadd.asm,然后加其加入到工程中。
在其它需要引用該函數的源文件中,添加以下聲明:
#include "stdafx.h" #include <windows.h> //聲明引用外部函數 EXTERN_C ULONG64 myAdd(ULONG64 u1,ULONG64 u2); int _tmain(int argc, _TCHAR* argv[]) { ULONG64 result = myAdd(0x111111111,0x333333333); printf("result = 0x%I64X\n",result); return 0; }
二、設置asm文件的生成方式
在asm文件上點擊右鍵,選擇“屬性”:
然后點擊左側的“常規”,“從生成中排除”選擇“否”,“項類型”選擇“自定義生成工具”,然后點擊應用。
此時在“常規”下面就會出現“自定義生成工具”的條目。
點擊它,設置“命令行”為 ml64 /Fo $(IntDir)%(fileName).obj /c %(fileName).asm
設置輸出為 $(IntDir)%(fileName).obj, 該項必須配置,否則VS認為該文件沒有設置輸出就會不處理它,同時它也告訴鏈接器到哪里去找這個obj文件。
上面的 $(IntDir)是一個宏,表示當前生成配置的目錄,比如"x64\Debug"。
經過以上配置之后,asm文件編譯生成的obj文件就會自動生成到相應配置的目錄。
三、生成工程
全部配置完成以后,就可以愉快地生成工程了。正常的輸出結果如下:
1>------ 已啟動生成: 項目: testasm, 配置: Release x64 ------ 1>生成啟動時間為 2016/4/10 9:45:36。 1>InitializeBuildStatus: 1> 正在創建“x64\Release\testasm.unsuccessfulbuild”,因為已指定“AlwaysCreate”。 1>CustomBuild: 1> Performing Custom Build Tools 1> Assembling: myAdd.asm 1> Microsoft (R) Macro Assembler (x64) Version 10.00.40219.01 1> Copyright (C) Microsoft Corporation. All rights reserved. 1> 1>ClCompile: 1> stdafx.cpp 1> testasm.cpp 1>Link: 1> 正在生成代碼 1> 已完成代碼的生成 1> testasm.vcxproj -> F:\x64Program\testasm\x64\Release\testasm.exe 1>FinalizeBuildStatus: 1> 正在刪除文件“x64\Release\testasm.unsuccessfulbuild”。 1> 正在對“x64\Release\testasm.lastbuildstate”執行 Touch 任務。 1> 1>生成成功。 1> 1>已用時間 00:00:01.11 ========== 生成: 成功 1 個,失敗 0 個,最新 0 個,跳過 0 個 ==========
如果沒什么意外的話,就會生成成功了。如果你編寫的asm文件有錯誤的話,在輸出中也能看到相應的提示,改掉錯誤就可以了。
至此,又可以愉快地使用匯編了呢~