一、 優(yōu)點(diǎn)
使用內(nèi)聯(lián)匯編可以在 C/C++ 代碼中嵌入?yún)R編語言指令,而且不需要額外的匯編和連接步驟。在 Visual C++ 中,內(nèi)聯(lián)匯編是內(nèi)置的編譯器,因此不需要配置諸如 MASM 一類的獨(dú)立匯編工具。這里,我們就以 Visual Studio .NET 2003 為背景,介紹在 Visual C++ 中使用內(nèi)聯(lián)匯的相關(guān)知識(shí)(如果是早期的版本,可能會(huì)有些許出入)。
內(nèi)聯(lián)匯編代碼可以使用 C/C++ 變量和函數(shù),因此它能非常容易地整合到 C/C++ 代碼中。它能做一些對(duì)于單獨(dú)使用 C/C++ 來說非常笨重或不可能完成的任務(wù)。
內(nèi)聯(lián)匯編的用途包括:
* 使用匯編語言編寫特定的函數(shù);
* 編寫對(duì)速度要求非常較高的代碼;
* 在設(shè)備驅(qū)動(dòng)程序中直接訪問硬件;
* 編寫 naked 函數(shù)的初始化和結(jié)束代碼。
二、 關(guān)鍵字
使用內(nèi)聯(lián)匯編要用到 __asm 關(guān)鍵字,它可以出現(xiàn)在任何允許 C/C++ 語句出現(xiàn)的地方。我們來看一些例子:
* 簡(jiǎn)單的 __asm 塊:
__asm
{
MOV AL, 2
MOV DX, 0xD007
OUT AL, DX
}
* 在每條匯編指令之前加 __asm 關(guān)鍵字:
__asm MOV AL, 2
__asm MOV DX, 0xD007
__asm OUT AL, DX
* 因?yàn)?__asm 關(guān)鍵字是語句分隔符,所以可以把多條匯編指令放在同一行:
__asm MOV AL, 2 __asm MOV DX, 0XD007 __asm OUT AL, DX
顯然,第一種方法與 C/C++ 的風(fēng)格很一致,并且把匯編代碼和 C/C++ 代碼清楚地分開,還避免了重復(fù)輸入 __asm 關(guān)鍵字,因此推薦使用第一種方法。
不像在 C/C++ 中的“{}”,__asm 塊的“{}”不會(huì)影響 C/C++ 變量的作用范圍。同時(shí),__asm 塊可以嵌套,而且嵌套也不會(huì)影響變量的作用范圍。
為了與低版本的 Visual C++ 兼容,_asm 和 __asm 具有相同的意義。另外,Visual C++ 支持標(biāo)準(zhǔn) C++ 的 asm 關(guān)鍵字,但是它不會(huì)生成任何指令,它的作用僅限于使編譯器不會(huì)出現(xiàn)編譯錯(cuò)誤。要使用內(nèi)聯(lián)匯編,必須使用 __asm 而不是 asm 關(guān)鍵字。
三、 匯編語言
1. 指令集
內(nèi)聯(lián)匯編支持 Intel Pentium 4 和 AMD Athlon 的所有指令。更多其它處理器的指令可以通過 _EMIT 偽指令來創(chuàng)建(_EMIT 偽指令說明見下文)。
2. MASM 表達(dá)式
在內(nèi)聯(lián)匯編代碼中,可以使用所有的 MASM 表達(dá)式(MASM 表達(dá)式是指用來計(jì)算一個(gè)數(shù)值或一個(gè)地址的操作符和操作數(shù)的組合)。
3. 數(shù)據(jù)指示符和操作符
雖然 __asm 塊中允許使用 C/C++ 的數(shù)據(jù)類型和對(duì)象,但它不能使用 MASM 指示符和操作符來定義數(shù)據(jù)對(duì)象。這里特別指出,__asm 塊中不允許 MASM 中的定義指示符(DB、DW、DD、DQ、DT 和 DF),也不允許使用 DUP 和 THIS 操作符。MASM 中的結(jié)構(gòu)和記錄也不再有效,內(nèi)聯(lián)匯編不接受 STRUC、RECORD、WIDTH 或者 MASK。
4. EVEN 和 ALIGN 指示符
盡管內(nèi)聯(lián)匯編不支持大多數(shù) MASM 指示符,但它支持 EVEN 和 ALIGN。當(dāng)需要的時(shí)候,這些指示符在匯編代碼里面加入 NOP 指令(空操作)使標(biāo)號(hào)對(duì)齊到特定邊界。這樣可以使某些處理器取指令時(shí)具有更高的效率。
5. MASM 宏指示符
內(nèi)聯(lián)匯編不是宏匯編,不能使用 MASM 宏指示符(MACRO、REPT、IRC、IRP 和 ENDM)和宏操作符(<>、!、&、% 和 .TYPE)。
6. 段
必須使用寄存器而不是名稱來指明段(段名稱“_TEXT”是無效的)。并且,段跨越必須顯式地說明,如 ES:[EBX]。
7. 類型和變量大小
在內(nèi)聯(lián)匯編中,可以用 LENGTH、SIZE 和 TYPE 來獲取 C/C++ 變量和類型的大? ?
* LENGTH 操作符用來取得 C/C++ 中數(shù)組的元素個(gè)數(shù)(如果不是一個(gè)數(shù)組,則結(jié)果為 1)。
* SIZE 操作符可以獲取 C/C++ 變量的大?。ㄒ粋€(gè)變量的大小是 LENGTH 和 TYPE 的乘積)。
* TYPE 操作符可以返回 C/C++ 類型和變量的大?。ㄈ绻兞渴且粋€(gè)數(shù)組,它得到的是數(shù)組中單個(gè)元素的大?。?。
例如,程序中定義了一個(gè) 8 維的整數(shù)型變量:
int iArray[8];
下面是 C 和匯編表達(dá)式中得到的 iArray 及其元素的相關(guān)值:
__asm C Size
LENGTH iArray sizeof(iArray)/sizeof(iArray[0]) 8
SIZE iArray sizeof(iArray) 32
TYPE iArray sizeof(iArray[0]) 4
8. 注釋
內(nèi)聯(lián)匯編中可以使用匯編語言的注釋,即“;”。例如:
__asm MOV EAX, OFFSET pbBuff ; Load address of pbBuff
因?yàn)?C/C++ 宏將會(huì)展開到一個(gè)邏輯行中,為了避免在宏中使用匯編語言注釋帶來的混亂,內(nèi)聯(lián)匯編也允許使用 C/C++ 風(fēng)格的注釋。
9. _EMIT 偽指令
_EMIT 偽指令相當(dāng)于 MASM 中的 DB,但是 _EMIT 一次只能在當(dāng)前代碼段(.text 段)中定義一個(gè)字節(jié)。例如:
__asm
{
JMP _CodeLabel
_EMIT 0x00 ; 定義混合在代碼段的數(shù)據(jù)
_EMIT 0x01
_CodeLabel: ; 這里是代碼
_EMIT 0x90 ; NOP指令
}
10. 寄存器使用
一般來說,不能假定某個(gè)寄存器在 __asm 塊開始的時(shí)候有已知的值。寄存器的值將不能保證會(huì)從 __asm 塊保留到另外一個(gè) __asm 塊中。
如果一個(gè)函數(shù)聲明為 __fastcall 調(diào)用方式,則其參數(shù)將通過寄存器而不是堆棧來傳遞。這將會(huì)使 __asm 塊產(chǎn)生問題,因?yàn)楹瘮?shù)無法被告知哪個(gè)參數(shù)在哪個(gè)寄存器中。如果函數(shù)接收了 EAX 中的參數(shù)并立即儲(chǔ)存一個(gè)值到 EAX 中的話,原來的參數(shù)將丟失掉。另外,在所有聲明為 __fastcall 的函數(shù)中,ECX 寄存器是必須一直保留的。為了避免以上的沖突,包含 __asm 塊的函數(shù)不要聲明為 __fastcall 調(diào)用方式。
* 提示:如果使用 EAX、EBX、ECX、EDX、ESI 和 EDI 寄存器,你不需要保存它。但如果你用到了 DS、SS、SP、BP 和標(biāo)志寄存器,那就應(yīng)該用 PUSH 保存這些寄存器。
* 提示:如果程序中改變了用于 STD 和 CLD 的方向標(biāo)志,必須將其恢復(fù)到原來的值。
四、 使用 C/C++ 元素
1. 可用的 C/C++ 元素
C/C++ 與匯編語言可以混合使用,在內(nèi)聯(lián)匯編中可以使用 C/C++ 變量以及很多其它的 C/C++ 元素,包括:
* 符號(hào),包括標(biāo)號(hào)、變量和函數(shù)名;
* 常量,包括符號(hào)常量和枚舉型成員;
* 宏定義和預(yù)處理指示符;
* 注釋,包括“/**/”和“//”;
* 類型名,包括所有 MASM 中合法的類型;
* typedef 名稱,通常使用 PTR 和 TYPE 操作符,或者使用指定的的結(jié)構(gòu)或枚舉成員。
在內(nèi)聯(lián)匯編中,可以使用 C/C++ 或匯編語言的基數(shù)計(jì)數(shù)法。例如,0x100 和 100H 是相等的。
2. 操作符使用
內(nèi)聯(lián)匯編中不能使用諸如“<<”一類的 C/C++ 操作符。但是,C/C++ 和 MASM 共有的操作符(比如“*”和“[]”操作符),都被認(rèn)為是匯編語言的操作符,是可以使用的。舉個(gè)例子:
int iArray[10];
__asm MOV iArray[6], BX ; Store BX at iArray + 6 (Not scaled)
iArray[6] = 0; // Store 0 at iArray+12 (Scaled)
* 提示:在內(nèi)聯(lián)匯編中,可以使用 TYPE 操作符使其與 C/C++ 一致。比如,下面兩條語句是一樣的:
__asm MOV iArray[6 * TYPE int], 0 ; Store 0 at iArray + 12
iArray[6] = 0; // Store 0 at iArray + 12
3. C/C++ 符號(hào)使用
在 __asm 塊中可以引用所有在作用范圍內(nèi)的 C/C++ 符號(hào),包括變量名稱、函數(shù)名稱和標(biāo)號(hào)。但是不能訪問 C++ 類的成員函數(shù)。
下面是在內(nèi)聯(lián)匯編中使用 C/C++ 符號(hào)的一些限制:
* 每條匯編語句只能包含一個(gè) C/C++ 符號(hào)。在一條匯編指令中,多個(gè)符號(hào)只能出現(xiàn)在 LENGTH、TYPE 或 SIZE 表達(dá)式中。
* 在 __asm 塊中引用函數(shù)必須先聲明。否則,編譯器將不能區(qū)別 __asm 塊中的函數(shù)名和標(biāo)號(hào)。
* 在 __asm 塊中不能使用對(duì)于 MASM 來說是保留字的 C/C++ 符號(hào)(不區(qū)分大小寫)。MASM 保留字包含指令名稱(如 PUSH)和寄存器名稱(如 ESI)等。
* 在 __asm 塊中不能識(shí)別結(jié)構(gòu)和聯(lián)合標(biāo)簽。
4. 訪問 C/C++ 中的數(shù)據(jù)
內(nèi)聯(lián)匯編的一個(gè)非常大的方便之處是它可以使用名稱來引用 C/C++ 變量。例如,如果 C/C++ 變量 iVar 在作用范圍內(nèi):
__asm MOV EAX, iVar ; Stores the value of iVar in EAX
如果 C/C++ 中的類、結(jié)構(gòu)或者枚舉成員具有唯一的名稱,則在 __asm 塊中可以只通過成員名稱來訪問(省略“.”操作符之前的變量名或 typedef 名稱)。然而,如果成員不是唯一的,你必須在“.”操作符之前加上變量名或 typedef 名稱。例如,下面的兩個(gè)結(jié)構(gòu)都具有 SameName 這個(gè)成員變量:
struct FIRST_TYPE
{
char *pszWeasel;
int SameName;
};
struct SECOND_TYPE
{
int iWonton;
long SameName;
};
如果按下面方式聲明變量:
struct FIRST_TYPE ftTest;
struct SECOND_TYPE stTemp;
那么,所有引用 SameName 成員的地方都必須使用變量名,因?yàn)?SameName 不是唯一的。另外,由于上面的 pszWeasel 變量具有唯一的名稱,你可以僅僅使用它的成員名稱來引用它:
__asm
{
MOV EBX, OFFSET ftTest
MOV ECX, [EBX]ftTest.SameName ; 必須使用“ftTest”
MOV ESI, [EBX]. pszWeasel ; 可以省略“ftTest”
}
* 提示:省略變量名僅僅是為了書寫代碼方便,生成的匯編指令還是一樣的。
5. 用內(nèi)聯(lián)匯編寫函數(shù)
如果用內(nèi)聯(lián)匯編寫函數(shù)的話,要傳遞參數(shù)和返回一個(gè)值都是非常容易的??聪旅娴睦樱容^一下用獨(dú)立匯編和內(nèi)聯(lián)匯編寫的函數(shù):
; PowerAsm.asm
; Compute the power of an integer
PUBLIC GetPowerAsm
_TEXT SEGMENT WORD PUBLIC 'CODE'
GetPowerAsm PROC
PUSH EBP ; Save EBP
MOV EBP, ESP ; Move ESP into EBP so we can refer
; to arguments on the stack
MOV EAX, [EBP+4] ; Get first argument
MOV ECX, [EBP+6] ; Get second argument
SHL EAX, CL ; EAX = EAX * (2 ^ CL)
POP EBP ; Restore EBP
RET ; Return with sum in EAX
GetPowerAsm ENDP
_TEXT ENDS
END
C/C++ 函數(shù)一般用堆棧來傳遞參數(shù),所以上面的函數(shù)中需要通過堆棧位置來訪問它的參數(shù)(在 MASM 或其它一些匯編工具中,也允許通過名稱來訪問堆棧參數(shù)和局部堆棧變量)。
下面的程序是使用內(nèi)聯(lián)匯編寫的:
// PowerC.c
#i nclude <Stdio.h>
int GetPowerC(int iNum, int iPower);
int main()
{
printf("3 times 2 to the power of 5 is %d\n", GetPowerC( 3, 5));
}
int GetPowerC(int iNum, int iPower)
{
__asm
{
MOV EAX, iNum ; Get first argument
MOV ECX, iPower ; Get second argument
SHL EAX, CL ; EAX = EAX * (2 to the power of CL)
}
// Return with result in EAX
}
使用內(nèi)聯(lián)匯編寫的 GetPowerC 函數(shù)可以通過參數(shù)名稱來引用它的參數(shù)。由于 GetPowerC 函數(shù)沒有執(zhí)行 C 的 return 語句,所以編譯器會(huì)給出一個(gè)警告信息,我們可以通過 #pragma warning 禁止生成這個(gè)警告。
內(nèi)聯(lián)匯編的其中一個(gè)用途是編寫 naked 函數(shù)的初始化和結(jié)束代碼。對(duì)于一般的函數(shù),編譯器會(huì)自動(dòng)幫我們生成函數(shù)的初始化(構(gòu)建參數(shù)指針和分配局部變量等)和結(jié)束代碼(平衡堆棧和返回一個(gè)值等)。 使用內(nèi)聯(lián)匯編,我們可以自己編寫干干凈凈的函數(shù)。當(dāng)然,此時(shí)我們必須自己動(dòng)手做一些有關(guān)函數(shù)初始化和掃尾的工作。例如:
void __declspec(naked) MyNakedFunction()
{
// Naked functions must provide their own prolog.
__asm
{
PUSH EBP
MOV ESP, EBP
SUB ESP, __LOCAL_SIZE
}
.
.
.
// And we must provide epilog.
__asm
{
POP EBP
RET
}
}
6. 調(diào)用 C/C++ 函數(shù)
內(nèi)聯(lián)匯編中調(diào)用聲明為 __cdecl 方式(默認(rèn))的 C/C++ 函數(shù)必須由調(diào)用者清除參數(shù)堆棧,下面是一個(gè)調(diào)用 C/C++ 函數(shù)例子:
#i nclude <Stdio.h>
char szFormat[] = "%s %s\n";
char szHello[] = "Hello";
char szWorld[] = " world";
void main()
{
__asm
{
MOV EAX, OFFSET szWorld
PUSH EAX
MOV EAX, OFFSET szHello
PUSH EAX
MOV EAX, OFFSET szFormat
PUSH EAX
CALL printf
// 壓入了 3 個(gè)參數(shù)在堆棧中,調(diào)用函數(shù)之后要調(diào)整堆棧
ADD ESP, 12
}
}
* 提示:參數(shù)是按從右往左的順序壓入堆棧的。
如果調(diào)用 __stdcall 方式的函數(shù),則不需要自己清除堆棧。因?yàn)檫@種函數(shù)的返回指令是 RET n,會(huì)自動(dòng)清除堆棧。大多數(shù) Windows API 函數(shù)均為 __stdcall 調(diào)用方式(僅除 wsprintf 等幾個(gè)之外),下面是一個(gè)調(diào)用 MessageBox 函數(shù)的例子:
#i nclude <Windows.h>
TCHAR g_tszAppName[] = TEXT("API Test");
void main()
{
TCHAR tszHello[] = TEXT("Hello, world!");
__asm
{
PUSH MB_OK OR MB_ICONINFORMATION
PUSH OFFSET g_tszAppName ; 全局變量用 OFFSET
LEA EAX, tszHello ; 局部變量用 LEA
PUSH EAX
PUSH 0
CALL DWORD PTR [MessageBox] &
//****************************************************************************
轉(zhuǎn)自:
http://hi.baidu.com/xocoder/blog/item/55dd5a12975d6a28dd5401e7.html
43"To be an effective leader, a public official must maintain the highest ethical and moral standards."
is a public official must maintain the highest ethical and moral standards to be an effective leader ,as the author asserts? I think we should take it to the case-to-case analysis.
Admittedly, in some cases, such like monarchy countries and religious nations, high ethical and moral standards are remarkable for leaders. Becaue those leaders are not only the politicians but also the spiritual leader. Their power don’t come from the Democratic elections ,but the religious belief. If their image of ethics collapse, it will threaten the leadership directly. Like dalai lama…Scandals on dalai lama
tends to render social chaos and breakdown of people's belief, which will even lead to a war at last. Therefore, high ethical and moral standards for spiritual or religious leaders are not only crucial, but also necessary.吹。。。。
But in the democracy society, which operates by its scientific belief ,the leader’s personality or Moral Charm is not that significant as the ancient time. The really thing that count is the leader’s governing philosophy, the Economic Policy which can bring his people to a better life. He moral or ethics charm is just a private thing which are not very crucial.
So , the leaders in the democracy system, is just a screw in a large machine , which could be replaced by any suitable person and it has not much thing to do with the leader’s moral image in he public. Like Bill Clinton ,who are always mentioned by his sex scandal, is of course a good leader in the US history .
On the other hand, even in democratic societies, moral charisma is useful and helpful for political leaders. A candidate with high moral reputation is more likely to win a campaign, which is the beginning to become an effective leader. When it comes to a decision maker, if he or she is famous for good morality, the policies are usually easier to be accepted by public. Let's take the Chinese Premier Wen (Premier Wen in China) as an example, who played an important role in the rescue in Sichuan Earthquake which killed (claimed) more than seventy thousand lives in 2008(災(zāi)難常用句型:e.g The hurricane claimed more than 5,000 lives。颶風(fēng)奪去了5000人的生命). His mercy and devoted figure moved millions of people all over the world. As a result, his leadership in rescuing activity rescue is convincing and his orders are implemented efficiency…Efficiently
which saved thousands of people buried underground in time. In this case, there is no doubt that the leader's personal moral charm improves the effect of Premier Wen's leadership.
In the final analysis , the ethic and morality of public leader could be very significant in some cases , especially to that spiritual leaders and religious leaders and it also benefits the leaders from democratic society as well. However, we have to notice that the real standard to evaluate a leader should base on his or her political achievement.