導航:首頁 > 源碼編譯 > 如何將asm編譯為dll

如何將asm編譯為dll

發布時間:2022-08-12 15:42:46

Ⅰ 如何編譯生成dll

創建DLL工程
這里,我們為了簡要說明DLL的原理,我們決定使用最簡單的編譯環境VC6.0,如下圖,我們先建立一個新的Win32 Dynamic-Link Library工程,名稱為「MyDLL」,在Visual Studio中,你也可以通過建立Win32控制台程序,然後在「應用程序類型」中選擇「DLL」選項,

點擊確定,選擇「一個空的DLL工程」,確定,完成即可。

一個簡單的dll
在第一步我們建立的工程中建立一個源碼文件」dllmain.cpp「,在「dllmain.cpp」中,鍵入如下代碼

[cpp] view plain
#include <Windows.h>
#include <stdio.h>

BOOL APIENTRY DllMain(HMODULE hMole, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
printf("DLL_PROCESS_ATTACH\n");
break;
case DLL_THREAD_ATTACH:
printf("DLL_THREAD_ATTACH\n");
break;
case DLL_THREAD_DETACH:
printf("DLL_THREAD_DETACH\n");
break;
case DLL_PROCESS_DETACH:
printf("DLL_PROCESS_DETACH\n");
break;
}
return TRUE;
}
之後,我們直接編譯,即可以在Debug文件夾下,找到我們生成的dll文件,「MyDLL.dll」,注意,代碼裡面的printf語句,並不是必須的,只是我們用於測試程序時使用。而DllMain函數,是dll的進入/退出函數。

實際上,讓線程調用DLL的方式有兩種,分別是隱式鏈接和顯式鏈接,其目的均是將DLL的文件映像映射進線程的進程的地址空間。我們這里只大概提一下,不做深入研究,如果感興趣,可以去看《Window高級編程指南》的第12章內容。
隱式鏈接調用
隱士地鏈接是將DLL的文件影響映射到進程的地址空間中最常用的方法。當鏈接一個應用程序時,必須制定要鏈接的一組LIB文件。每個LIB文件中包含了DLL文件允許應用程序(或另一個DLL)調用的函數的列表。當鏈接器看到應用程序調用了某個DLL的LIB文件中給出的函數時,它就在生成的EXE文件映像中加入了信息,指出了包含函數的DLL文件的名稱。當操作系統載入EXE文件時,系統查看EXE文件映像的內容來看要裝入哪些DLL,而後試圖將需要的DLL文件映像映射到進程的地址空間中。當尋找DLL時,系統在系列位置查找文件映像。

1.包含EXE映像文件的目錄
2.進程的當前目錄
3.Windows系統的目錄
4.Windows目錄
5.列在PATH環境變數中的目錄

這種方法,一般都是在程序鏈接時控制,反映在鏈接器的配置上,網上大多數講的各種庫的配置,比如OPENGL或者OPENCV等,都是用的這種方法

顯式鏈接調用
這里我們只提到兩種函數,一種是載入函數
[cpp] view plain
HINSTANCE LoadLibrary(LPCTSTR lpszLibFile);

HINSTANCE LoadLibraryEx(LPCSTR lpszLibFile,HANDLE hFile,DWORD dwFlags);
返回值HINSTANCE值指出了文件映像映射的虛擬內存地址。如果DLL不能被映進程的地址空間,函數就返回NULL。你可以使用類似於

[cpp] view plain
LoadLibrary("MyDLL")
或者

[cpp] view plain
LoadLibrary("MyDLL.dll")
的方式進行調用,不帶後綴和帶後綴在搜索策略上有區別,這里不再詳解。

顯式釋放DLL

在顯式載入DLL後,在任意時刻可以調用FreeLibrary函數來顯式地從進程的地址空間中解除該文件的映像。
[cpp] view plain
BOOL FreeLibrary(HINSTANCE hinstDll);
這里,在同一個進程中調用同一個DLL時,實際上還牽涉到一個計數的問題。這里也不在詳解。
線程可以調用GetMoleHandle函數:

[cpp] view plain
GetMoleHandle(LPCTSTR lpszMoleName);
來判斷一個DLL是否被映射進進程的地址空間。例如,下面的代碼判斷MyDLL.dll是否已被映射到進程的地址空間,如果沒有,則裝入它:

[cpp] view plain
HINSTANCE hinstDll;
hinstDll = GetMoleHandle("MyDLL");
if (hinstDll == NULL){
hinstDll = LoadLibrary("MyDLL");
}
實際上,還有一些函數,比如 GetMoleFileName用來獲取DLL的全路徑名稱,FreeLibraryAndExitThread來減少DLL的使用計數並退出線程。具體內容還是參見《Window高級編程指南》的第12章內容,此文中不適合講太多的內容以至於讀者不能一下子接受。

DLL的進入與退出函數

說到這里,實際上只是講了幾個常用的函數,這一個小節才是重點。
在上面,我們看到的MyDLL的例子中,有一個DllMain函數,這就是所謂的進入/退出函數。系統在不同的時候調用此函數。這些調用主要提供信息,常常被DLL用來執行進程級或線程級的初始化和清理工作。如果你的DLL不需要這些通知,就不必再你的DLL源代碼中實現此函數,例如,如果你創建的DLL只含有資源,就不必實現該函數。但如果有,則必須像我們上面的格式。
DllMain函數中的ul_reason_for_call參數指出了為什麼調用該函數。該參數有4個可能值: DLL_PROCESS_ATTACH、DLL_THREAD_ATTACH、DLL_THREAD_DETACH、DLL_PROCESS_DETACH。
其中,DLL_PROCESS_ATTACH是在一個DLL首次被映射到進程的地址空間時,系統調用它的DllMain函數,傳遞的ul_reason_for_call參數為DLL_PROCESS_ATTACH。這只有在首次映射時發生。如果一個線程後來為已經映射進來的DLL調用LoadLibrary或LoadLibraryEx,操作系統只會增加DLL的計數,它不會再用DLL_PROCESS_ATTACH調用DLL的DllMain函數。
而DLL_PROCESS_DETACH是在DLL被從進程的地址空間解除映射時,系統調用它的DllMain函數,傳遞的ul_reason_for_call值為DLL_PROCESS_DETACH。我們需要注意的是,當用DLL_PROCESS_ATTACH調用DLL的DllMain函數時,如果返回FALSE,說明初始化不成功,系統仍會用DLL_PROCESS_DETACH調用DLL的DllMain。因此,必須確保沒有清理那些沒有成功初始化的東西。
DLL_THREAD_ATTACH:當進程中創建一個線程時,系統察看當前映射到進程的地址空間中的所有DLL文件映像,並用值DLL_THREAD_ATTACH調用所有的這些DLL的DllMain函數。該通知告訴所有的DLL去執行線程級的初始化。注意,當映射一個新的DLL時,進程中已有的幾個線程在運行,系統不會為已經運行的線程用值DLL_THREAD_ATTACH調用DLL的DllMain函數。
而DLL_THREAD_DETACH,如果線程調用ExitThread來終結(如果讓線程函數返回而不是調用ExitThread,系統會自動調用ExitThread),系統察看當前映射到進程空間的所有DLL文件映像,並用值DLL_THREAD_DETACH來調用所有的DLL的DllMain函數。該通知告訴所有的DLL去執行線程級的清理工作。
這里,我們需要注意的是,如果線程的終結是因為系統中的一個線程調用了TerminateThread,系統就不會再使用DLL_THREAD_DETACH來調用DLL和DllMain函數。這與TerminateProcess一樣,不再萬不得已時,不要使用。
下面,我們貼出《Window高級編程指南》中的兩個圖來說明上述四種參數的調用情況。

好的,介紹了以上的情況,下面,我們來繼續實踐,這次,建立一個新的空的win32控制台工程TestDLL,不再多說,代碼如下:

[cpp] view plain
#include <iostream>
#include <Windows.h>
using namespace std;

DWORD WINAPI someFunction(LPVOID lpParam)
{
cout << "enter someFunction!" << endl;
Sleep(1000);
cout << "This is someFunction!" << endl;
Sleep(1000);
cout << "exit someFunction!" << endl;
return 0;
}

int main()
{
HINSTANCE hinstance = LoadLibrary("MyDLL");
if(hinstance!=NULL)
{
cout << "Load successfully!" << endl;
}else {
cout << "Load failed" << endl;
}
HANDLE hThread;
DWORD dwThreadId;

cout << "createThread before " << endl;
hThread = CreateThread(NULL,0,someFunction,NULL,0,&dwThreadId);
cout << "createThread after " << endl;
cout << endl;

Sleep(3000);

cout << "waitForSingleObject before " << endl;
WaitForSingleObject(hThread,INFINITE);
cout << "WaitForSingleObject after " << endl;
cout << endl;

FreeLibrary(hinstance);
return 0;
}

代碼很好理解,但是前提是,你必須對線程有一定的概念。另外,注意,我們上面編譯的獲得的「MyDLL.dll"必須拷貝到能夠讓我們這個工程找到的地方,也就是上面我們提到的搜索路徑中的一個地方。
這里,我們先貼結果,當然,這只是在我機器上其中某次運行結果。

有了上面我們介紹的知識,這個就不是很難理解,主進程在調用LoadLibrary時,用DLL_PROCESS_ATTACH調用了DllMain函數,而線程創建時,用DLL_THREAD_ATTACH調用了DllMain函數,而由於主線程和子線程並行的原因,可能輸出的時候會有打斷。但是,這樣反而能讓我們更清楚的理解程序。

Ⅱ 如何編譯ASM文件

1. 在DOS命令中轉到要編譯文件所在的目錄.
2.輸入MASM.EXE空格+文件名.三下回車,就生成了OBJ文件,
3.link.exe空格+所生成的OBJ文件,再按三下回車,就生成了exe文件.

Ⅲ swmm怎麼編譯生成dll文件

如果需要改寫SWMM模型的源代碼,通常需要重新編譯生成新的動態鏈接庫,也就是常說的DLL,將SWMM 5源碼編譯為DLL的主要步驟如下:
1. 下載SWMM模型計算引擎源代碼後解壓,裡麵包含了模型代碼源文件。在對代碼進行必要的個性化修改後(如果不需要修改代碼,就完全沒有必要自己重新編譯了,安裝SWMM軟體後,安裝文件下就有計算引擎的DLL文件)就可以進行接下來的工作了。
2. 新建工程:以VC6.0為例,點擊文件/新建→工程;選擇」win32 dynmaic-link library」,輸入工程名字,如SWMM 5,在「位置」下輸入新工程存儲的路徑,點擊下方的「確定」;
3. 選擇「一個空的工程」,點擊「完成」;在彈出的對話框中點擊「確定」;
4. 「工程」菜單中選擇「添加到菜單」→文件,然後把文件夾中的包括頭文件在內的SWMM源文件(均以.c,.h後綴)全部添加到工程。
5. 在swmm5.c中取消define DLL前的注釋,使代碼為如下形式:
//#define CLE
//#define SOL
#define DLL
6. 選擇「組建」中的「編譯 SWMM5 」,在出現的對話框選擇「是」,然後再選擇」build」中的」execute swmm5″就完成了整個文件的編譯和執行。生成的debug文件夾中有swmm5.DLL。
7. 最後,把swmm5.def文件添加到工程中重新編譯一次。

Ⅳ 把一個.asm文件鏈接成一個可執行文件需要哪些工具

可執行文件不會被編譯,編譯器只讀取各個源代碼文件(.cpp)並生成目標文件(.obj),obj和dll會被鏈接器進行鏈接然後生成可執行文件(.exe)。
調用別人寫好的程序有幾種方法:
1:如果是在編譯時把別人的成果加入到自己的程序中,就需要源代碼文件(.cpp)或者頭文件(.h),跟你自己的代碼放到一起編譯。
2:如果是在鏈接時加入別人的代碼,你需要別人的動態鏈接庫文件(.dll)和對應的庫文件、頭文件(.lib,.h)。
3:如果是在運行時想要執行別人的程序,你可以使用 LoadLibrary 等函數動態載入 DLL。或者使用 ShellExecute 等函數啟動另外一個程序。

Ⅳ 在怎樣情況下把代碼編譯成dll文件

如果使用的是VS,可以進行如下操作:
打開VS, 文件-新建-新建項目-其他語言-Visual C++ - Win32 控制台應用程序。
單擊確定後,彈出對話框,按照對話框「下一步」提示進行操作。
將要編譯的C文件拷貝到CreateDLL項目中,.h文件就放到頭文件夾的目錄下,.c文件放到源文件目錄下,注意後綴名為.c的文件都要改成.cpp,否則編譯會出錯。
注意:申明函數時必須參照上圖紅框標示出來的規則,在Function.cpp文件中必須要引入對應的#include CreateDLL.h。
選中所有需要編譯成dll的cpp文件,右鍵-屬性-預編譯頭-不使用預編譯頭,然後選擇 「生成」即可,這樣在項目的Debug文件夾下面便可找到CreateDLL.dll文件

Ⅵ c#使用命令行編譯生成dll文件

C#使用csc.exe編譯程序,csc使用/target:library(縮寫: /t:library)參數生成Dll文件。
其它參數如下:
Visual C# 編譯器選項
- 輸出文件 -
/out:<文件> 指定輸出文件名(默認值: 包含主類的文件或第一個文件的基名稱)
/target:exe 生成控制台可執行文件(默認) (縮寫: /t:exe)
/target:winexe 生成 Windows 可執行文件 (縮寫: /t:winexe)
/target:library 生成庫 (縮寫: /t:library)
/target:mole 生成能添加到其他程序集的模塊 (縮寫: /t:mole)
/target:appcontainerexe 生成 Appcontainer 可執行文件 (縮寫: /t:appcontainerexe)
/target:winmdobj 生成 WinMDExp 使用的 Windows 運行時中間文件 (縮寫: /t:winmdobj)
/doc:<文件> 要生成的 XML 文檔文件
/platform:<字元串> 限制可以在其上運行此代碼的平台: x86、Itanium、x64、arm、anycpu32bitpreferred 或 anycpu。默認值為 anycpu。

- 輸入文件 -
/recurse:<通配符> 根據通配符規范,包括當前目錄和子目錄下的所有文件
/reference:<別名>=<文件> 使用給定的別名從指定的程序集文件引用元數據 (縮寫: /r)
/reference:<文件列表> 從指定的程序集文件引用元數據 (縮寫: /r)
/addmole:<文件列表> 將指定的模塊鏈接到此程序集中
/link:<文件列表> 嵌入指定的互操作程序集文件中的元數據 (縮寫: /l)

- 資源 -
/win32res:<文件> 指定 Win32 資源文件(.res)
/win32icon:<文件> 對輸出使用此圖標
/win32manifest:<文件> 指定 Win32 清單文件(.xml)
/nowin32manifest 不包括默認 Win32 清單
/resource:<資源信息> 嵌入指定的資源 (縮寫: /res)
/linkresource:<資源信息> 將指定的資源鏈接到此程序集 (縮寫: /linkres)
其中 resinfo 的格式是 <file>[,<string name>[,public|private]]

- 代碼生成 -
/debug[+|-] 發出調試信息
/debug:{full|pdbonly} 指定調試類型(「full」是默認類型,可以將調試程序附加到正在運行的程序)
/optimize[+|-] 啟用優化 (縮寫: /o)

- 錯誤和警告 -
/warnaserror[+|-] 將所有警告報告為錯誤
/warnaserror[+|-]:<警告列表> 將特定警告報告為錯誤
/warn:<n> 設置警告等級(0-4) (縮寫: /w)
/nowarn:<警告列表> 禁用特定的警告消息

- 語言 -
/checked[+|-] 生成溢出檢查
/unsafe[+|-] 允許「不安全」代碼
/define:<符號列表> 定義條件編譯符號 (縮寫: /d)
/langversion:<字元串> 指定語言版本模式: ISO-1、ISO-2、3、4、5 或 Default

- 安全性 -
/delaysign[+|-] 僅使用強名稱密鑰的公共部分對程序集進行延遲簽名
/keyfile:<文件> 指定強名稱密鑰文件
/keycontainer:<字元串> 指定強名稱密鑰容器
/highentropyva[+|-] 啟用高平均信息量的 ASLR

- 雜項 -
@<文件> 有關更多選項,請閱讀響應文件
/help 顯示此用法信息 (縮寫: /?)
/nologo 取消編譯器版權信息
/noconfig 不要自動包含 CSC.RSP 文件

- 高級 -
/baseaddress:<地址> 要生成的庫的基址
/bugreport:<文件> 創建「Bug 報告」文件
/codepage:<n> 指定打開源文件時要使用的代碼頁
/utf8output 以 UTF-8 編碼格式輸出編譯器消息
/main:<類型> 指定包含入口點的類型(忽略所有其他可能的入口點) (縮寫: /m)
/fullpaths 編譯器生成完全限定路徑
/filealign:<n> 指定用於輸出文件節的對齊方式
/pdb:<文件> 指定調試信息文件名(默認值: 擴展名為 .pdb 的輸出文件名)
/errorendlocation 輸出每個錯誤的結束位置的行和列
/preferreilang 指定首選輸出語言名稱。
/nostdlib[+|-] 不引用標准庫(mscorlib.dll)
/subsystemversion:<字元串> 指定此程序集的子系統版本
/lib:<文件列表> 指定要在其中搜索引用的附加目錄
/errorreport:<字元串> 指定如何處理內部編譯器錯誤: prompt、send、queue 或 none。默認值為 queue。
/appconfig:<文件> 指定一個包含程序集綁定設置的應用程序配置文件
/moleassemblyname:<字元串> 此模塊所屬程序集的名稱

Ⅶ 32位ASM代碼,怎麼改編為64位,並編譯DLL

運行庫組件
你可以在騰訊電腦管家的電腦診斷中找到軟體問題,選擇丟失VC++組件,點擊立即修復。

在工具箱,打開電腦診所,丟失.Dll 文件,進行一鍵修復

Ⅷ 如何編譯生成dll文件以及如何調用dll文件

1.vs2015下生成DLL文件
文件->新建->項目
點擊確定選擇dll選項和空項目選項
點擊完成
為項目添加c++源文件mydll.cpp
[cpp] view plain
在CODE上查看代碼片派生到我的代碼片
extern "C" // 此處extern "c" 為解決c/c++兼容問題
{
_declspec(dllexport)int add(int a, int b)
{
return a + b;
}
extern "C"
{
_declspec(dllexport)int sub(int a, int b)
{
return a - b;
}
}
編譯生成 成功後會在工程根目錄生成Win32Project1.dll文件
2.對dll文件的調用
顯示調用動態鏈接庫
新建C++工程
把生成的 Win32Project1.dll 文件拷貝到 剛才新建的工程目錄下
在工程中新建源文件寫入代碼為
[cpp] view plain
在CODE上查看代碼片派生到我的代碼片
#include<iostream>
#include<windows.h>
void main()
{
HINSTANCE mydll = LoadLibrary("Win32Project1.dll"); //載入dll文件
if (mydll == NULL)
{
return;
}
int(*add)(int, int) =( int (*)(int ,int )) GetProcAddress(mydll, "add");//獲取函數指針
/*
等價於
typedef int(*myadd)(int, int); //給 函數指針int (*)(int, int ) 取別名 myadd
myadd a = (myadd) GetProcAddress(mydll,"add"); //獲取函數地址
*/
if (add == NULL)
{
return;
}
std::cout << add(1, 2);
std::cin.get();
}
編譯並運行即可。

Ⅸ word中怎樣將文件類型ASM改成DLL。明天考試 急求!!!

運行CMD
在DOS狀態下直接就可以更改文件名和文件格式(如a.asm 可以用ren a.asm a.dll)就可以了

閱讀全文

與如何將asm編譯為dll相關的資料

熱點內容
數學奇跡神奇運演算法 瀏覽:359
大廠的程序員的水平如何 瀏覽:700
遺傳演算法入門經典書籍 瀏覽:878
源碼炮台腳本 瀏覽:620
在位編輯命令 瀏覽:347
曲式分析基礎教程pdf 瀏覽:14
php生成靜態html頁面 瀏覽:964
怎麼分割pdf 瀏覽:813
壓縮垃圾報警器 瀏覽:629
小公司一般都用什麼伺服器 瀏覽:968
java獲取時間gmt時間 瀏覽:821
為什麼csgo一直連接不到伺服器 瀏覽:504
安卓登ins需要什麼 瀏覽:836
機器人演算法的難點 瀏覽:226
全自動化編程 瀏覽:728
程序員高薪限制 瀏覽:693
壓縮圖片壓縮 瀏覽:75
美國發明解壓魔方 瀏覽:302
電腦怎麼備案網上伺服器 瀏覽:515
旅行商問題Python寫法 瀏覽:954