小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

程序中嵌入?yún)R編的實(shí)例

 quasiceo 2014-01-13
文章來(lái)自:http://www./Article/kfyy/vc/jszl/200708/5714.html

C51編譯器能對(duì)C語(yǔ)言程序進(jìn)行高效率的編譯,生成高效簡(jiǎn)潔的代碼,在大多數(shù)的應(yīng)用場(chǎng)合,采用C語(yǔ)言編程即可完成預(yù)期的任務(wù),但是,在有些場(chǎng)合還是會(huì)用到匯編,例如在下面的幾種情況下,采用匯編可能會(huì)有很多好處:

1、已有程序的移植:在單片機(jī)領(lǐng)域工作很久的工程人員可能會(huì)保留有很多的早期用匯編語(yǔ)言編制的程序模塊,并且這些模塊已經(jīng)經(jīng)過(guò)實(shí)際應(yīng)用的驗(yàn)證,如果重新用C編程,可能工作量很大,這時(shí)就可以用嵌入?yún)R編的方式把以前的匯編模塊植入新的應(yīng)用,可以明顯的加快開(kāi)發(fā)的進(jìn)度。

2、局部功能需要足夠短的執(zhí)行時(shí)間:在有些應(yīng)用中,部分的功能模塊需要有很高的執(zhí)行效率,而有些匯編的指令在C中沒(méi)有對(duì)應(yīng)的指令,這給我們對(duì)單片機(jī)的高效操作帶來(lái)困難,嵌入?yún)R編可是我們的程序執(zhí)行更有效率。

3、對(duì)一些特定地址進(jìn)行操作:在C中我們要對(duì)特定地址進(jìn)行讀寫,一般用以下兩種方式:用_AT_指令定義變量;定義指向外部端口或數(shù)據(jù)地址的指針;在匯編中只需要使用MOVX A,@DPTR或MOVX @DPTR,A就可以了,這樣可以增強(qiáng)程序的可讀性。

4、其他的需要匯編的應(yīng)用:在這里我們不可能舉出所有可能要用匯編的例子,在你的應(yīng)用中,你可能在一個(gè)或多個(gè)應(yīng)用中感到C語(yǔ)言的不足,而需要用到匯編指令,請(qǐng)你記住,可以在C中嵌入?yún)R編子程序,這對(duì)你的程序非常有用。

首先介紹一下調(diào)用匯編的參數(shù)傳遞規(guī)則,見(jiàn)下表

傳遞的參數(shù) char、1字節(jié)指針 int、2字節(jié)指針 long、float 一般指針
第一個(gè)參數(shù) R7 R6,R7 R4~R7 R1,R2,R3
第二個(gè)參數(shù) R5 R4,R5 R1,R2,R3
第三個(gè)參數(shù) R3 R2,R3 無(wú) R1,R2,R3

在下面的例子中我們首先給出一個(gè)C程序調(diào)用匯編的例子,先說(shuō)明一下,在這個(gè)例子中,你完全可以用C完成,我用這個(gè)例子,只是為了說(shuō)明嵌入?yún)R編的方法。

例1:

下面是C語(yǔ)言的主程序

#include <REG52.H>
#include <stdio.h>
extern char asm(char c,char b);
bit VAL;
void main (void)
{
  char out=0x49;
  char direct;
  char key;
  SCON = 0x50; /* SCON: mode 1, 8-bit UART, enable rcvr */
  TMOD |= 0x20; /* TMOD: timer 1, mode 2, 8-bit reload */
  TH1 = 0xfd; /* TH1: reload value for 9600 baud @ 11.0592MHz */
  TR1 = 1; /* TR1: timer 1 run */
  TI = 1; /* TI: set TI to send first char of UART */
  VAL=0;
  while (1)
  {
    key=getchar();
    if(key=='R')
    {
      direct=0X01;
      out=asm(out,direct); /*匯編子程序調(diào)用*/
      printf ("Right rotate\n");
    }
    if(key=='L')
    {
      direct=0X02;
      out=asm(out,direct); /*匯編子程序調(diào)用*/
      printf ("Left rotate\n");
    }
    printf("%bx\n",out);
  }
}

下面是匯編的子程序(文件名稱asmtest.asm)

NAME ASM
PR?_asm?ASMTEST SEGMENT CODE
BI?_asm?ASMTEST SEGMENT BIT
PUBLIC ?_asm?BIT
PUBLIC _asm
RSEG ?BI?_asm?ASMTEST
_asm?BIT:
VAL: DBIT 1
RSEG ?PR?_asm?ASMTEST
_asm:
MOV A,R7
MOV C,VAL
DJNZ R5,JP1
RRC A
JP1:
DJNZ R5,JP2
RLC A
JP2:
MOV 90h,A
MOV R7,A
MOV VAL,C
RET
END

現(xiàn)在對(duì)這個(gè)例子簡(jiǎn)短的說(shuō)明,這個(gè)例子是用來(lái)驅(qū)動(dòng)一個(gè)不帶細(xì)分的三相步進(jìn)電機(jī),用的是循環(huán)移位的指令來(lái)實(shí)現(xiàn)的,由于一個(gè)字節(jié)是8位,如果算上進(jìn)位位,共9位,通過(guò)付值,可以得到這樣的數(shù)100100100,大家可以看到任意取中間的3位,相鄰的每3位與它都一樣,這樣我們就可以去中間的3位輸出到端口去驅(qū)動(dòng)一個(gè)三相的步進(jìn)電機(jī),通過(guò)對(duì)這個(gè)9位的二進(jìn)制數(shù)進(jìn)行循環(huán)移位,可以實(shí)現(xiàn)電機(jī)的步進(jìn),在51系列單片機(jī)中有兩條指令可以幫助我們進(jìn)行循環(huán)移位操作,這就是RRC A和RLC A指令,我們只要把第九位保存好,在需要移位操作時(shí),把它付給PSW中C,再執(zhí)行循環(huán)移位就可以了。

在這個(gè)例子中,我發(fā)現(xiàn)了幾個(gè)需要注意的地方:

1、在C程序中,我不能把VAL變量設(shè)為extern類型,否則在連接時(shí)會(huì)有警告,導(dǎo)致數(shù)值不能傳遞;

2、在匯編模塊中,不能把SEGMENT BIT段置為OVERLAYABLE即可覆蓋段,如果置為可覆蓋段,那么在進(jìn)入?yún)R編模塊時(shí)VAL變量值丟失;

3、如果把VAL變量作為函數(shù)的參數(shù)傳遞,出現(xiàn)在返回后在執(zhí)行printf函數(shù)后變量值丟失;

上面是本人寫的一個(gè)C程序調(diào)用匯編的小例子,在本例中的幾個(gè)printf函數(shù)是為了便于在Keil C51中模擬調(diào)試時(shí)觀察運(yùn)行結(jié)果的,在實(shí)際應(yīng)用中可以將這幾條去掉,這只是一個(gè)簡(jiǎn)短的示例,目的在于介紹一下C調(diào)用匯編的用法,希望對(duì)大家有幫助,同時(shí)由于本人水平有限,在程序中有些地方可能仍有不周到之處,歡迎廣大單片機(jī)高手不吝指出。

vc中使用匯編asm文件


use ASM and CPP together:
1. create an ASM file
;;;;;;;;;;;;; asmsrc.asm:
.386
.model flat, stdcall
option casemap :none
.code

myasmproc proc dw1:DWORD,dw2:DWORD
mov eax,dw1
add eax,dw2
ret
myasmproc endp
end
;;;;;;;;;;;;end of asmsrc.asm

2. create a VC project name: useasm, type console application, A "Hello World" application

3. move the asm file to your project directory, then in VC project menu->Add to Project...->Files...
Files of type change to "all files", then you can select the asmsrc.asm, and click OK

4.in workspace window, FileView tab, select asmsrc.asm, right click to select "settings..." menu, custom build tab, put the following in commands edit box :
d:\masm32\bin\ml.exe /nologo /coff /Zf /c /Sa $(InputName).asm
put the following in Outputs edit box:
$(InputName).obj

5.edit your useasm.cpp as the following:
//////////////////////useasm.cpp///////////////////////////////
#i nclude "stdafx.h"
#i nclude <windows.h>
extern "C" int __stdcall myasmproc(DWORD d1,DWORD d2);
int main(int argc, char* argv[])
{
printf("test of using cpp and asm together, if it works, it is done by masterz,otherwise I don't know who write this^_^\n");
int ret=myasmproc(22,33);
printf("ASM result:%d\n",ret);
return 0;
}

//////////////////////end of useasm.cpp///////////////////////////////

6. build the project and run it, it works.

notes: I assume you have installed masm32V8(you can get it from http://www./masmdl.htm) at D:\masm32

轉(zhuǎn)載 sunwen:VC內(nèi)聯(lián)ASM匯編學(xué)習(xí)筆記【轉(zhuǎn)】

目的:學(xué)習(xí)在VC中進(jìn)行ASM匯編語(yǔ)言程序設(shè)計(jì)的方法,以提高底層應(yīng)用能力.

由于在VC中進(jìn)行匯編不需要額外的編譯器和聯(lián)接器,且可以處理VC中不能處理的一些事情,而且可以使用在C中的變量,所以,非常方便.但是它并不支持所有的MASM宏和數(shù)據(jù)指示符.

下面的三種方法基本上都可以使用在VC中:

__asm
{
mov al, 2
mov dx, 0xD007
out al, dx
}


__asm mov al, 2
__asm mov dx, 0xD007
__asm out al, dx


__asm mov al, 2 __asm mov dx, 0xD007 __asm out al, dx


顯然,最好的是第一種.

_emit相當(dāng)于MASM中的DB.

雖然內(nèi)聯(lián)匯編可以使用C/C++中的變量,但是它不能夠自己定義變量.

可以使用EVEN和ALIGN.

不能夠使用MASM宏.

必須使用寄存器來(lái)說(shuō)明段,跨越段必須顯式地說(shuō)明,如ES:[BX].

在內(nèi)聯(lián)匯編中的類型和變量大小:

我們可以使用LENGTH來(lái)取得C/C++中的數(shù)組中的元素個(gè)數(shù),如果不是一個(gè)數(shù)組,則結(jié)果為一.使用SIZE來(lái)取得C/C++中變量的大小,一個(gè)變量的大小是LENGTH和TYPE的乘積.TYPE用來(lái)取得一個(gè)變量的大小,如果是一個(gè)數(shù)組,它得到的一個(gè)數(shù)組中的單個(gè)元素的大小.

VC中允許使用MMX指令.

內(nèi)聯(lián)的ASM代碼并不易于移植,所以,應(yīng)當(dāng)盡量避免.
在__asm塊中可以使用的元素:

1.符號(hào)包括函數(shù)名

2.常數(shù)和enum類型

3.宏和預(yù)處理成員

4.注釋

5.MASM中的類型名

6.typedef,PTR,TYPE

寄存器:

一般來(lái)說(shuō),在__asm塊開(kāi)始的時(shí)候,寄存器是空的.不能在兩個(gè)__asm之間保存寄存器的值.

如果一個(gè)函數(shù)被聲明成了__fastcall,則其參數(shù)將放在寄存器中,這將給寄存器的管理帶來(lái)問(wèn)題.所以,如果要將一個(gè)函數(shù)聲明成__fastcall,必須保存ECX寄存器.為了避免以上的沖突,在聲明為_(kāi)_fastcall的函數(shù)中不要有__asm塊.如果用了/Gr編譯選項(xiàng)(它全局的變成__fastcall),將每個(gè)函數(shù)聲明成__cdecl或者_(dá)_stdcall,這個(gè)屬性告訴編譯器用傳統(tǒng)的C方法.

不用保存EAX, EBX, ECX, EDX, ESI, or EDI寄存器.但卻需要保存DS, SS, SP, BP, and標(biāo)志寄存器.

如果程序中改變了用于STD和CLD的方向標(biāo)志,你必須將其恢復(fù)到原來(lái)的值.

跳轉(zhuǎn):

可以使用goto和ASM指定跳到label或__asm以外的程序段中去.例:

void func( void )
{
goto C_Dest; /* Legal: correct case */
goto c_dest; /* Error: incorrect case */

goto A_Dest; /* Legal: correct case */
goto a_dest; /* Legal: incorrect case */

__asm
{
jmp C_Dest ; Legal: correct case
jmp c_dest ; Legal: incorrect case

jmp A_Dest ; Legal: correct case
jmp a_dest ; Legal: incorrect case

a_dest: ; __asm label
}

C_Dest: /* C label */
return;
}

不要使用函數(shù)名稱當(dāng)作label,否則將使其跳到函數(shù)執(zhí)行而不是label處.如下所示:

; BAD TECHNIQUE: using library function name as label
jne exit
.
.
.
exit:
; More __asm code follows

美元符號(hào)$用于指定當(dāng)前位置,如下所用,常用于條件跳轉(zhuǎn):

jne $+5 ; next instruction is 5 bytes long
jmp farlabel
; $+5
.
.
.
farlabel:
調(diào)用C中的函數(shù):

下面是一個(gè)例子:

#i nclude

char format[] = "%s %s\n";
char hello[] = "Hello";
char world[] = "world";
void main( void )
{
__asm
{
mov eax, offset world
push eax
mov eax, offset hello
push eax
mov eax, offset format
push eax
call printf
//clean up the stack so that main can exit cleanly
//use the unused register ebx to do the cleanup
pop ebx
pop ebx
pop ebx
}
}


注意:函數(shù)參數(shù)是從右向左壓棧.

不能夠訪問(wèn)C++中的類成員函數(shù).可以訪問(wèn)extern "C"函數(shù).

VC不會(huì)優(yōu)化__asm塊中的代碼.

轉(zhuǎn)載 在Visual C++中使用內(nèi)聯(lián)匯編[轉(zhuǎn)]新一篇: 用匯編實(shí)現(xiàn)strcmp函數(shù) | 舊一篇: sunwen:VC內(nèi)聯(lián)ASM匯編學(xué)習(xí)筆記【轉(zhuǎn)】

http://www./article/g/2005-08-05/a0951608.shtml

本文出自 Yonsm 大哥之手
(老羅:這可是精品中的精品哦!強(qiáng)烈推薦!大家好好學(xué)學(xué) :))

在 Visual C++ 中使用內(nèi)聯(lián)匯編

一、內(nèi)聯(lián)匯編的優(yōu)缺點(diǎn)
因?yàn)樵赩isual C++中使用內(nèi)聯(lián)匯編不需要額外的編譯器和聯(lián)接器,且可以處理Visual C++中不能處理的一些事情,而且可以使用在C/C++中的變量,所以非常方便。內(nèi)聯(lián)匯編主要用于如下場(chǎng)合:
1.使用匯編語(yǔ)言寫函數(shù);
2.對(duì)速度要求非常高的代碼;
3.設(shè)備驅(qū)動(dòng)程序中直接訪問(wèn)硬件;
4."Naked" Call的初始化和結(jié)束代碼。
//(."Naked",理解了意思,但是不知道怎么翻譯^_^,大概就是不需要C/C++的編譯器(自作聰明)生成的函數(shù)初始化和收尾代碼,請(qǐng)參看MSDN的"Naked <I>function</I>s"的說(shuō)明)
內(nèi)聯(lián)匯編代碼不易于移植,如果你的程序打算在不同類型的機(jī)器(比如x86和Alpha)上運(yùn)行,應(yīng)當(dāng)盡量避免使用內(nèi)聯(lián)匯編。這時(shí)候你可以使用MASM,因?yàn)镸ASM支持更方便的的宏指令和數(shù)據(jù)指示符。

二、內(nèi)聯(lián)匯編關(guān)鍵字
在Visual C++使用內(nèi)聯(lián)匯編用到的是__asm關(guān)鍵字,這個(gè)關(guān)鍵字有兩種使用方法:
1.簡(jiǎn)單__asm塊
__asm
{
MOV AL, 2
MOV DX, 0xD007
OUT AL, DX
}
2.在每條匯編指令之前加__asm關(guān)鍵字
__asm MOV AL, 2
__asm MOV DX, 0xD007
__asm OUT AL, DX
因?yàn)開(kāi)_asm關(guān)鍵字是語(yǔ)句分隔符,因此你可以把匯編指令放在同一行:
__asm MOV AL, 2 __asm MOV DX, 0XD007 __asm OUT AL, DX
顯然,第一種方法和C/C++的風(fēng)格很一致,并且有很多其它優(yōu)點(diǎn),因此推薦使用第一種方法。
不象在C/C++中的"{}",__asm塊的"{}"不會(huì)影響C/C++變量的作用范圍。同時(shí),__asm塊可以嵌套,嵌套也不會(huì)影響變量的作用范圍。

三、在__asm塊中使用匯編語(yǔ)言
1.內(nèi)聯(lián)匯編指令集
內(nèi)聯(lián)匯編完全支持的Intel 486指令集,允許使用MMX指令。不支持的指令可以使用_EMIT偽指令定義(_EMIT偽指令說(shuō)明見(jiàn)下文)。
2.MASM表達(dá)式
內(nèi)聯(lián)匯編可以使用MASM中的表達(dá)式。比如: MOV EAX, 1。
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或者M(jìn)ASK。
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.段說(shuō)明
必須使用寄存器來(lái)說(shuō)明段,跨越段必須顯式地說(shuō)明,如ES:[BX]。
7.類型和變量大小
我們可以使用LENGTH來(lái)取得C/C++中的數(shù)組中的元素個(gè)數(shù),如果不是一個(gè)數(shù)組,則結(jié)果為一。使用SIZE來(lái)取得C/C++中變量的大小,一個(gè)變量的大小是LENGTH和TYPE的乘積。TYPE用來(lái)取得一個(gè)變量的大小,如果是一個(gè)數(shù)組,它得到的一個(gè)數(shù)組中的單個(gè)元素的大小。
8.注釋
可以使用C/C++的注釋,但推薦用ASM的注釋,即";"號(hào)。
9._EMIT偽指令
_EMIT偽指令相當(dāng)于MASM中的DB,但一次只能定義一個(gè)字節(jié),比如:
__asm
{
JMP _CodeOfAsm
_EMIT 0x00 ; 定義混合在代碼段的數(shù)據(jù)
_EMIT 0x01
_CodeOfAsm:
; 這里是代碼
_EMIT 0x90 ; NOP指令
}

四、在__asm塊中使用C/C++語(yǔ)言元素
C/C++與匯編可以混合使用,在內(nèi)聯(lián)匯編可以使用C/C++的變量和很多其它C/C++的元素。在__asm塊中可以使用以下C/C++元素:
1.符號(hào),包括標(biāo)號(hào)、變量和函數(shù)名;
2.常量,包括符號(hào)常量和枚舉型(enum)成員;
3.宏定義和預(yù)處理指示符;
4.注釋,包括"/**/"和"http://";
5.類型名,包括所有MASM中合法的類型
6.typedef名稱, 像PTR、TYPE、特定的結(jié)構(gòu)成員或枚舉成員這樣的通用操作符。
在__asm塊中,可以使用C/C++或ASM的基數(shù)計(jì)數(shù)法(比如: 0x100和100H是相等的)。
__asm塊中不能使用像<<一類的C/C++操作符。C/C++和MASM通用的操作符,比如"*"和"[]"操作符,都被認(rèn)為是匯編語(yǔ)言的操作符。舉個(gè)例子:
int array[[10]];
__asm MOV array[[6]], BX ; Store BX at array+6 (not scaled)
array[[6]] = 0; /* Store 0 at array+12 (scaled) */
* 小技巧: 內(nèi)聯(lián)匯編中,你可以使用TYPE操作符使作其與C一致。比如,下面兩條語(yǔ)句是一樣的:
__asm MOV array[[6 * TYPE int ], 0 ; Store 0 at array + 12
array[[6]] = 0; /* Store 0 at array + 12 */
內(nèi)聯(lián)匯編能通過(guò)變兩名直接引用C/C++的變量。__asm塊中可以引用任何符號(hào),包括變量名。
如果C/C++中的類、結(jié)構(gòu)或者枚舉成員具有唯一的名稱,如果在"."操作符之前不指定變量或者typedef名稱,則__asm塊中只能引用成員名稱。然而,如果成員不是唯一的,你必須在"."操作符之前加上變量名或typedef名稱。例如,下面的兩個(gè)結(jié)構(gòu)都具有same_name這個(gè)成員變量:
struct first_type
{
char *weasel;
int same_name;
};
struct second_type
{
int wonton;
long same_name;
};
如果按下面聲明變量:
struct first_type hal;
struct second_type oat;
那么,所有引用same_name成員的地方都必須使用變量名,因?yàn)閟ame_name不是唯一的。另外,上面的weasel變量具有唯一的名稱,你可以僅僅使用它的成員名稱來(lái)引用它:
__asm
{
MOV EBX, OFFSET hal
MOV ECX, [EBX]hal.same_name ; 必須使用 ’hal’
MOV ESI, [EBX].weasel ; 可以省略 ’hal’
}
注意,省略了變量名僅僅是為了寫代碼的方便,生成的匯編指令的還是一樣的。
可以不受限制地訪問(wèn)C++成員變量,但是不能調(diào)用C++的成員函數(shù)。

五、寄存器使用
一般來(lái)說(shuō),在__asm塊開(kāi)始的時(shí)候,寄存器是空的,不能在兩個(gè)__asm之間保存寄存器的值。(這是MSDN上說(shuō)的,我在實(shí)際使用時(shí)發(fā)現(xiàn),好像并不是這樣。不過(guò)它是說(shuō)"一般",我是特殊:))
如果一個(gè)函數(shù)被聲明成了__fastcall,則其參數(shù)將放在寄存器中,這將給寄存器的管理帶來(lái)問(wèn)題。所以,如果要將一個(gè)函數(shù)聲明成__fastcall,必須保存ECX寄存器。為了避免以上的沖突,在聲明為_(kāi)_fastcall的函數(shù)中不要有__asm塊。如果用了/Gr編譯選項(xiàng)(它全局的變成__fastcall),將每個(gè)函數(shù)聲明成__cdecl或者_(dá)_stdcall,這個(gè)屬性告訴編譯器用傳統(tǒng)的C方法。
如果使用EAX、EBX、ECX、EDX、ESI和EDI寄存器,你不需要保存它;但如果你用到了DS、 SS、SP、BP和標(biāo)志寄存器,那就應(yīng)該P(yáng)USH保存這些寄存器。
如果程序中改變了用于STD和CLD的方向標(biāo)志,你必須將其恢復(fù)到原來(lái)的值。

六、轉(zhuǎn)跳
可以在C里面使用goto調(diào)到__asm塊中的標(biāo)號(hào)處,也可以在__asm塊中轉(zhuǎn)跳到__asm塊里面和外面的標(biāo)號(hào)處。__asm塊內(nèi)的標(biāo)號(hào)是不區(qū)分大小寫的(指令、指示符等也是不區(qū)分大小寫的)。例:
void func()
{
goto C_Dest; /* 合法 */
goto c_dest; /* 錯(cuò)誤 */
goto A_Dest; /* 合法 */
goto a_dest; /* 合法 */
__asm
{
JMP C_Dest ; 合法
JMP c_dest ; MSDN上說(shuō)合法,但是我在VS.NET中編譯,認(rèn)為這樣不合法
JMP A_Dest ; 合法
JMP a_dest ; 合法
a_dest: ; __asm 標(biāo)號(hào)
}
C_Dest: /* C的標(biāo)號(hào) */
return;
}

不要使用函數(shù)名稱當(dāng)作標(biāo)號(hào),否則將使其跳到函數(shù)執(zhí)行而不是標(biāo)號(hào)處。如下所示:
; 錯(cuò)誤: 使用函數(shù)名作為標(biāo)號(hào)
JNE exit
.
.
.
exit:
; 下面是更多的ASM代碼

美元符號(hào)$用于指定當(dāng)前位置,如下所用,常用于條件跳轉(zhuǎn):
JNE $Content$5 ; 下面這條指令的長(zhǎng)度是5個(gè)字節(jié)
JMP farlabel
;$Content$5,跳到了這里
.
.
.
farlabel:

七、調(diào)用函數(shù)
內(nèi)聯(lián)匯編調(diào)用C/C++函數(shù)必須自己清除堆棧,下面是一個(gè)調(diào)用C/C++函數(shù)例子:
#include <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
//內(nèi)聯(lián)匯編調(diào)用C函數(shù)必須自己清除堆棧
//用不使用的EBX寄存器清除堆棧,或ADD ESP, 12
POP EBX
POP EBX
POP EBX
}
}
注意:函數(shù)參數(shù)是從右向左壓棧。
不能夠訪問(wèn)C++中的類成員函數(shù),但是可以訪問(wèn)extern "C"函數(shù)。
如果調(diào)用Windows API函數(shù),則不需要自己清除堆棧,因?yàn)锳PI的返回指令是RET n,會(huì)自動(dòng)清除堆棧
比如下面的例子:
#include <windows.h>
char szAppName[] = "API Test";
void main()
{
char szHello[] = "Hello, world!";
__asm
{
PUSH MB_OK OR MB_ICONINformATION
PUSH OFFSET szAppName ; 全局變量用OFFSET
LEA EAX, szHello ; 局部變量用LEA
PUSH EAX
PUSH 0
CALL DWORD PTR [MessageBoxA] ; 注意這里,我費(fèi)了好大周折才發(fā)現(xiàn)不是CALL MessageBoxA
}
}
一般來(lái)說(shuō),在Visual C++中使用內(nèi)聯(lián)匯編是為了提高速度,因此這些函數(shù)調(diào)用盡可能用C/C++寫。

新一篇: 在Visual C++中使用內(nèi)聯(lián)匯編[轉(zhuǎn)] | 舊一篇: AT&T x86 asm 語(yǔ)法[轉(zhuǎn)]

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多