真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

關(guān)于C語(yǔ)言中EXPORT函數(shù)的信息

C語(yǔ)言調(diào)用匯編程序時(shí),使用哪些寄存器來(lái)傳遞參數(shù)?

C語(yǔ)言與匯編語(yǔ)言混合編程應(yīng)遵守的規(guī)則\r\nARM編程中使用的C語(yǔ)言是標(biāo)準(zhǔn)C語(yǔ)言,ARM的開發(fā)環(huán)境實(shí)際上就是嵌入了一個(gè)C語(yǔ)言的集成開發(fā)環(huán)境,只不過(guò)這個(gè)開發(fā)環(huán)境與ARM的硬件緊密相關(guān)。\r\n在使用C語(yǔ)言時(shí),要用到和匯編語(yǔ)言的混合編程。若匯編代碼較為簡(jiǎn)潔,則可使用直接內(nèi)嵌匯編的方法;否則要將匯編程序以文件的形式加入到項(xiàng)目中,按照ATPCS(ARM/Thumb過(guò)程調(diào)用標(biāo)準(zhǔn),ARM/Thumb Procedure Call Standard)的規(guī)定與C程序相互調(diào)用與訪問。\r\n在C程序和ARM匯編程序之間相互調(diào)用時(shí)必須遵守ATPCS規(guī)則。ATPCS規(guī)定了一些子程序間調(diào)用的基本規(guī)則,哪寄存器的使用規(guī)則,堆棧的使用規(guī)則和參數(shù)的傳遞規(guī)則等。\r\n1)寄存器的使用規(guī)則\r\n子程序之間通過(guò)寄存器r0~r3來(lái)傳遞參數(shù),當(dāng)參數(shù)個(gè)數(shù)多于4個(gè)時(shí),使用堆棧來(lái)傳遞參數(shù)。此時(shí)r0~r3可記作A1~A4。\r\n在子程序中,使用寄存器r4~r11保存局部變量。因此當(dāng)進(jìn)行子程序調(diào)用時(shí)要注意對(duì)這些寄存器的保存和恢復(fù)。此時(shí)r4~r11可記作V1~V8。\r\n寄存器r12用于保存堆棧指針SP,當(dāng)子程序返回時(shí)使用該寄存器出棧,記作IP。\r\n寄存器r13用作堆棧指針,記作SP。寄存器r14稱為鏈接寄存器,記作LR。該寄存器用于保存子程序的返回地址。\r\n寄存器r15稱為程序計(jì)數(shù)器,記作PC。\r\n2)堆棧的使用規(guī)則\r\nATPCS規(guī)定堆棧采用滿遞減類型(FD,Full Descending),即堆棧通過(guò)減小存儲(chǔ)器地址而向下增長(zhǎng),堆棧指針指向內(nèi)含有效數(shù)據(jù)項(xiàng)的最低地址。\r\n3)參數(shù)的傳遞規(guī)則\r\n整數(shù)參數(shù)的前4個(gè)使用r0~r3傳遞,其他參數(shù)使用堆棧傳遞;浮點(diǎn)參數(shù)使用編號(hào)最小且能夠滿足需要的一組連續(xù)的FP寄存器傳遞參數(shù)。\r\n子程序的返回結(jié)果為一個(gè)32位整數(shù)時(shí),通過(guò)r0返回;返回結(jié)果為一個(gè)64位整數(shù)時(shí),通過(guò)r0和r1返回;依此類推。結(jié)果為浮點(diǎn)數(shù)時(shí),通過(guò)浮點(diǎn)運(yùn)算部件的寄存器F0、D0或者S0返回。\r\n2、匯編程序調(diào)用C程序的方法\r\n匯編程序的書寫要遵循ATPCS規(guī)則,以保證程序調(diào)用時(shí)參數(shù)正確傳遞。在匯編程序中調(diào)用C程序的方法為:首先在匯編程序中使用IMPORT偽指令事先聲明將要調(diào)用的C語(yǔ)言函數(shù);然后通過(guò)BL指令來(lái)調(diào)用C函數(shù)。\r\n例如在一個(gè)C源文件中定義了如下求和函數(shù):\r\nint add(int x,int y){\r\nreturn(x+y);\r\n}\r\n調(diào)用add()函數(shù)的匯編程序結(jié)構(gòu)如下:\r\nIMPORT add ;聲明要調(diào)用的C函數(shù)\r\n??\r\nMOV r0,1\r\nMOV r1,2\r\nBL add ;調(diào)用C函數(shù)add\r\n??\r\n當(dāng)進(jìn)行函數(shù)調(diào)用時(shí),使用r0和r1實(shí)現(xiàn)參數(shù)傳遞,返回結(jié)果由r0帶回。函數(shù)調(diào)用結(jié)束后,r0的值變成3。\r\n3、C程序調(diào)用匯編程序的方法\r\nC程序調(diào)用匯編程序時(shí),匯編程序的書寫也要遵循ATPCS規(guī)則,以保證程序調(diào)用時(shí)參數(shù)正確傳遞。在C程序中調(diào)用匯編子程序的方法為:首先在匯編程序中使用EXPORT偽指令聲明被調(diào)用的子程序,表示該子程序?qū)⒃谄渌募斜徽{(diào)用;然后在C程序中使用extern關(guān)鍵字聲明要調(diào)用的匯編子程序?yàn)橥獠亢瘮?shù)。\r\n例如在一個(gè)匯編源文件中定義了如下求和函數(shù):\r\nEXPORT add ;聲明add子程序?qū)⒈煌獠亢瘮?shù)調(diào)用\r\n??\r\nadd ;求和子程序add\r\nADD r0,r0,r1\r\nMOV pc,lr\r\n??\r\n在一個(gè)C程序的main()函數(shù)中對(duì)add匯編子程序進(jìn)行了調(diào)用:\r\nextern int add (int x,int y); //聲明add為外部函數(shù)\r\nvoid main(){\r\nint a=1,b=2,c;\r\nc=add(a,b); //調(diào)用add子程序\r\n??\r\n}\r\n當(dāng)main()函數(shù)調(diào)用add匯編子程序時(shí),變量a、b的值會(huì)給了r0和r1,返回結(jié)果由r0帶回,并賦值給變量c。函數(shù)調(diào)用結(jié)束后,變量c的值變成3。\r\n4、C程序中內(nèi)嵌匯編語(yǔ)句\r\n在C語(yǔ)言中內(nèi)嵌匯編語(yǔ)句可以實(shí)現(xiàn)一些高級(jí)語(yǔ)言不能實(shí)現(xiàn)或者不容易實(shí)現(xiàn)的功能。對(duì)于時(shí)間緊迫的功能也可以通過(guò)在C語(yǔ)言中內(nèi)嵌匯編語(yǔ)句來(lái)實(shí)現(xiàn)。內(nèi)嵌的匯編器支持大部分ARM指令和Thumb指令,但是不支持諸如直接修改PC實(shí)現(xiàn)跳轉(zhuǎn)的底層功能,也不能直接引用C語(yǔ)言中的變量。\r\n嵌入式匯編語(yǔ)句在形式上獨(dú)立定義的函數(shù)體,其語(yǔ)法格式為:\r\n__asm\r\n{\r\n指令[;指令]\r\n??\r\n[指令]\r\n}\r\n其中“__asm”為內(nèi)嵌匯編語(yǔ)句的關(guān)鍵字,需要特別注意的是前面有兩個(gè)下劃線。指令之間用分號(hào)分隔,如果一條指令占據(jù)多行,除最后一行外都要使用連字符“\”。\r\n5、基于ARM的C語(yǔ)言與匯編語(yǔ)言混合編程舉例\r\n下面給出了一個(gè)向串口不斷發(fā)送0x55的例子:\r\n該工程的啟動(dòng)代碼使用匯編語(yǔ)言編寫,向串口發(fā)送數(shù)據(jù)使用C語(yǔ)言實(shí)現(xiàn),下面是啟動(dòng)代碼的整體框架:\r\n??\r\nIMPORT Main\r\nAREA Init,CODE,READONLY;\r\nENTRY\r\n??\r\nBL Main ;跳轉(zhuǎn)到Main()函數(shù)處的C/C++程序\r\n??\r\nEND ;標(biāo)識(shí)匯編程序結(jié)束\r\n \r\n下面是使用C語(yǔ)言編寫的主函數(shù):\r\n#include "..\inc\config.h" //將有關(guān)硬件定義的頭文件包含進(jìn)來(lái)\r\nunsigned char data; //定義全局變量\r\n \r\nvoid main(void){\r\nTarget_Init(); //對(duì)目標(biāo)板的硬件初始化\r\nDelay(10); //延時(shí)\r\ndata=0x55; //給全局變量賦值\r\nwhile(1) {\r\nUart_Printf("%x",data); //向串口送數(shù)\r\nDelay(10);\r\n}\r\n}

成都創(chuàng)新互聯(lián)專注于晉城企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè),成都商城網(wǎng)站開發(fā)。晉城網(wǎng)站建設(shè)公司,為晉城等地區(qū)提供建站服務(wù)。全流程按需定制制作,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

一個(gè)程序中可以實(shí)現(xiàn)既有c語(yǔ)言,又有匯編語(yǔ)言嗎?

是可以的,一種是在C語(yǔ)言中使用"_ _asm" 如,_ _asm{ 匯編語(yǔ)言程序};

第二種是定義全局變量,這樣c,匯編都可以訪問。c中用extern,在匯編中EXPORT導(dǎo)出

第三種是在匯編中IMPORT(c語(yǔ)言的函數(shù)名),然后用 BL或者CALL跳轉(zhuǎn)到c語(yǔ)言中

C語(yǔ)言寫的程序,幫改成DLL

建立一個(gè)dll工程就可以了,扔進(jìn)去編下

關(guān)于c語(yǔ)言創(chuàng)建dll文件及dll文件的調(diào)用和一點(diǎn)設(shè)想 選擇自 Garriot 的 Blog

關(guān)鍵字 關(guān)于c語(yǔ)言創(chuàng)建dll文件及dll文件的調(diào)用和一點(diǎn)設(shè)想

出處

近來(lái)又有人在群里問如何用c語(yǔ)言編制dll文件(動(dòng)態(tài)鏈接庫(kù))。

原來(lái)沒有對(duì)這個(gè)問題太在意過(guò),也沒有嘗試過(guò)任何解決方案,畢竟原來(lái)我是用vb的(現(xiàn)在用.net),做個(gè)dll只不過(guò)是點(diǎn)選一下建立activeX dll工程的圖標(biāo)而已。今天在網(wǎng)上與朋友聊天,看了他指給我的幾個(gè)幾個(gè)文件,用MingW將C程序編譯成dll文件的例子,我恍然大悟,原來(lái)講C程序編譯成dll文件只不過(guò)是在要公開的接口函數(shù)聲明前面加上幾個(gè)特定的修飾符而已。于是用dev-cpp建了個(gè)dll的默認(rèn)文檔,一切都很明了。(我把源代碼貼在下面)

/*dll.h文件*/

#ifndef _DLL_H_

#define _DLL_H_

#if BUILDING_DLL

# define DLLIMPORT __declspec (dllexport)

#else /* Not BUILDING_DLL */

# define DLLIMPORT __declspec (dllimport)

#endif /* Not BUILDING_DLL */

DLLIMPORT void HelloWorld (void);

#endif /* _DLL_H_ */

/*dllmain.c文件*/

/* Replace "dll.h" with the name of your header */

#include "dll.h"

#include windows.h

#include stdio.h

#include stdlib.h

DLLIMPORT void HelloWorld ()

{

MessageBox (0, "Hello World from DLL!\n", "Hi", MB_ICONINFORMATION);

}

BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ ,

DWORD reason /* Reason this function is being called. */ ,

LPVOID reserved /* Not used. */ )

{

switch (reason)

{

case DLL_PROCESS_ATTACH:

break;

case DLL_PROCESS_DETACH:

break;

case DLL_THREAD_ATTACH:

break;

case DLL_THREAD_DETACH:

break;

}

/* Returns TRUE on success, FALSE on failure */

return TRUE;

}

關(guān)于以上代碼的幾點(diǎn)解釋:

一、__declspec (dllexport):這是關(guān)鍵,它標(biāo)志著這個(gè)這個(gè)函數(shù)將成為對(duì)外的接口。(以下是我在網(wǎng)上下載的dllexport、dllimport、_declspec的一些說(shuō)明):

使用包含在DLL的函數(shù),必須將其導(dǎo)入。導(dǎo)入操作時(shí)通過(guò)dllimport來(lái)完成的,dllexport和dllimport都是vc(visual C++)和bc(Borland C++)所支持的擴(kuò)展的關(guān)鍵字。但是dllexport和dllimport關(guān)鍵字不能被自身所使用,因此它的前面必須有另一個(gè)擴(kuò)展關(guān)鍵字__declspec。通用格式如下:__declspec(specifier)其中specifier是存儲(chǔ)類標(biāo)示符。對(duì)于DLL,specifier將是dllexport和dllimport。而且為了簡(jiǎn)化說(shuō)明導(dǎo)入和導(dǎo)出函數(shù)的語(yǔ)句,用一個(gè)宏名來(lái)代替__declspec.在此程序中,使用的是DllExport。如果用戶的DLL被編譯成一個(gè)C++程序,而且希望C程序也能使用它,就需要增加“C”的連接說(shuō)明。#define DllExport extern "C"__declspec(dllexport),這樣就避免了標(biāo)準(zhǔn)C++命名損壞。(當(dāng)然,如果讀者正在編譯的是C程序,就不要加入extern “C”,因?yàn)椴恍枰?,而且編譯器也不接受它)。

二、BOOL APIENTRY DllMain ()說(shuō)明:(以下是我在網(wǎng)上收集的資料)

1、每一個(gè)DLL必須有一個(gè)入口點(diǎn),DllMain是一個(gè)缺省的入口函數(shù)。DllMain負(fù)責(zé)初始化(Initialization)和結(jié)束(Termination)工作,每當(dāng)一個(gè)新的進(jìn)程或者該進(jìn)程的新的線程訪問DLL時(shí),或者訪問DLL的每一個(gè)進(jìn)程或者線程不再使用DLL或者結(jié)束時(shí),都會(huì)調(diào)用DllMain。但是,使用TerminateProcess或TerminateThread結(jié)束進(jìn)程或者線程,不會(huì)調(diào)用DllMain。

DllMain的函數(shù)原型:

BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)

{

switch(ul_reason_for_call)

{

case DLL_PROCESS_ATTACH:

.......

case DLL_THREAD_ATTACH:

.......

case DLL_THREAD_DETACH:

.......

case DLL_PROCESS_DETACH:

.......

return TRUE;

}

}

參數(shù):

hMoudle:是動(dòng)態(tài)庫(kù)被調(diào)用時(shí)所傳遞來(lái)的一個(gè)指向自己的句柄(實(shí)際上,它是指向_DGROUP段的一個(gè)選擇符);

ul_reason_for_call:是一個(gè)說(shuō)明動(dòng)態(tài)庫(kù)被調(diào)原因的標(biāo)志。當(dāng)進(jìn)程或線程裝入或卸載動(dòng)態(tài)連接庫(kù)的時(shí)候,操作系統(tǒng)調(diào)用入口函數(shù),并說(shuō)明動(dòng)態(tài)連接庫(kù)被調(diào)用的原因。它所有的可能值為:

DLL_PROCESS_ATTACH: 進(jìn)程被調(diào)用;

DLL_THREAD_ATTACH: 線程被調(diào)用;

DLL_PROCESS_DETACH: 進(jìn)程被停止;

DLL_THREAD_DETACH: 線程被停止;

lpReserved:是一個(gè)被系統(tǒng)所保留的參數(shù)。

看到這里,我想大家應(yīng)該會(huì)對(duì)將c程序編譯成dll文件有了個(gè)大體的概念。

關(guān)于對(duì)于dll文件的使用,我在vb.net里做了以下測(cè)試:

首先用vs.net 2003新建一個(gè)vb.net應(yīng)用程序。

然后在工程屬性中引用System.Runtime.InteropServices命名空間。

然后在默認(rèn)的窗體文件中添加如下代碼:

Public Class Form1

Inherits System.Windows.Forms.Form

#Region " Windows 窗體設(shè)計(jì)器生成的代碼 "

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Hello()

End Sub

End Class

Module test

Sub main()

Dim frm As New Form1

Application.Run(frm)

End Sub

DllImport("test.dll", EntryPoint:="HelloWorld", setlasterror:=True) Public Sub Hello()

End Sub

End Module

然后把上面用devcpp生成的test.dll放入工程bin目錄下,測(cè)試成功。

關(guān)于dll文件的一點(diǎn)設(shè)想:

關(guān)于多語(yǔ)言創(chuàng)建dll文件和動(dòng)態(tài)使用dll文件,我感覺應(yīng)該是插件技術(shù)plugin技術(shù)最直接的實(shí)現(xiàn)方式。特別是現(xiàn)在的.net平臺(tái),為動(dòng)態(tài)導(dǎo)入dll文件中的函數(shù)提供了更簡(jiǎn)易的方法。一個(gè)實(shí)現(xiàn)插件的基本思想可以是,在主程序和插件程序內(nèi)做出一個(gè)規(guī)定的通訊方式,比如將一個(gè)可以代表使用插件功能的對(duì)象,由主程序創(chuàng)建對(duì)應(yīng)插件程序的對(duì)象,然后由插件程序傳址調(diào)用,調(diào)用修改后的對(duì)象中保存了插件功能信息(比如插件名稱、功能函數(shù)指針等),然后再由主程序進(jìn)行處理。

以下是網(wǎng)上摘抄的一點(diǎn)資料:

動(dòng)態(tài)鏈接庫(kù)中定義有兩種函數(shù):導(dǎo)出函數(shù)(export function)和內(nèi)部函數(shù)(internal function)。導(dǎo)出函數(shù)可以被其它模塊調(diào)用,內(nèi)部函數(shù)在定義它們的DLL程序內(nèi)部使用。

輸出函數(shù)的方法有以下幾種:

1、傳統(tǒng)的方法

在模塊定義文件的EXPORT部分指定要輸入的函數(shù)或者變量。語(yǔ)法格式如下:

entryname[=internalname] [@ordinal[NONAME]] [DATA] [PRIVATE]

其中:

entryname是輸出的函數(shù)或者數(shù)據(jù)被引用的名稱;

internalname同entryname;

@ordinal表示在輸出表中的順序號(hào)(index);

NONAME僅僅在按順序號(hào)輸出時(shí)被使用(不使用entryname);

DATA表示輸出的是數(shù)據(jù)項(xiàng),使用DLL輸出數(shù)據(jù)的程序必須聲明該數(shù)據(jù)項(xiàng)為_declspec(dllimport)。

上述各項(xiàng)中,只有entryname項(xiàng)是必須的,其他可以省略。

對(duì)于“C”函數(shù)來(lái)說(shuō),entryname可以等同于函數(shù)名;但是對(duì)“C++”函數(shù)(成員函數(shù)、非成員函數(shù))來(lái)說(shuō),entryname是修飾名??梢詮?map映像文件中得到要輸出函數(shù)的修飾名,或者使用DUMPBIN /SYMBOLS得到,然后把它們寫在.def文件的輸出模塊。DUMPBIN是VC提供的一個(gè)工具。

如果要輸出一個(gè)“C++”類,則把要輸出的數(shù)據(jù)和成員的修飾名都寫入.def模塊定義文件。

2、在命令行輸出

對(duì)鏈接程序LINK指定/EXPORT命令行參數(shù),輸出有關(guān)函數(shù)。

3、使用MFC提供的修飾符號(hào)_declspec(dllexport)

在要輸出的函數(shù)、類、數(shù)據(jù)的聲明前加上_declspec(dllexport)的修飾符,表示輸出。__declspec(dllexport)在C調(diào)用約定、C編譯情況下可以去掉輸出函數(shù)名的下劃線前綴。extern "C"使得在C++中使用C編譯方式成為可能。在“C++”下定義“C”函數(shù),需要加extern “C”關(guān)鍵詞。用extern "C"來(lái)指明該函數(shù)使用C編譯方式。輸出的“C”函數(shù)可以從“C”代碼里調(diào)用。

例如,在一個(gè)C++文件中,有如下函數(shù):

extern "C" {void __declspec(dllexport) __cdecl Test(int var);}

其輸出函數(shù)名為:Test

MFC提供了一些宏,就有這樣的作用。

AFX_CLASS_IMPORT:__declspec(dllexport)

AFX_API_IMPORT:__declspec(dllexport)

AFX_DATA_IMPORT:__declspec(dllexport)

AFX_CLASS_EXPORT:__declspec(dllexport)

AFX_API_EXPORT:__declspec(dllexport)

AFX_DATA_EXPORT:__declspec(dllexport)

AFX_EXT_CLASS: #ifdef _AFXEXT

AFX_CLASS_EXPORT

#else

AFX_CLASS_IMPORT

AFX_EXT_API:#ifdef _AFXEXT

AFX_API_EXPORT

#else

AFX_API_IMPORT

AFX_EXT_DATA:#ifdef _AFXEXT

AFX_DATA_EXPORT

#else

AFX_DATA_IMPORT

像AFX_EXT_CLASS這樣的宏,如果用于DLL應(yīng)用程序的實(shí)現(xiàn)中,則表示輸出(因?yàn)開AFX_EXT被定義,通常是在編譯器的標(biāo)識(shí)參數(shù)中指定該選項(xiàng)/D_AFX_EXT);如果用于使用DLL的應(yīng)用程序中,則表示輸入(_AFX_EXT沒有定義)。

要輸出整個(gè)的類,對(duì)類使用_declspec(_dllexpot);要輸出類的成員函數(shù),則對(duì)該函數(shù)使用_declspec(_dllexport)。如:

class AFX_EXT_CLASS CTextDoc : public CDocument

{

}

extern "C" AFX_EXT_API void WINAPI InitMYDLL();

這幾種方法中,最好采用第三種,方便好用;其次是第一種,如果按順序號(hào)輸出,調(diào)用效率會(huì)高些;最次是第二種。

作者Blog:


文章標(biāo)題:關(guān)于C語(yǔ)言中EXPORT函數(shù)的信息
URL網(wǎng)址:http://weahome.cn/article/ddohcij.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部