c語言嵌入彙編pic,c++ 嵌入彙編

本文目錄一覽:

C語言怎樣嵌入彙編

用宏指令asm就可以實現C中嵌入彙編了。

比如:

void func()

{

C語言代碼……

#pragma asm

MOV R6,#23

DELAY2:

MOV R7,#191

DELAY1:

DJNZ R7,DELAY1

DJNZ R6,DELAY2

RET

#pragma endasm

C語言代碼……

}

C語言中怎麼嵌入彙編

在 Visual C++ 中使用內聯彙編- –

使用內聯彙編可以在 C/C++ 代碼中嵌入彙編語言指令,而且不需要額外的彙編和連接步驟。在 Visual C++ 中,內聯彙編是內置的編譯器,因此不需要配置諸如 MASM 一類的獨立彙編工具。這裡,我們就以 Visual Studio .NET 2003 為背景,介紹在 Visual C++ 中使用內聯匯的相關知識(如果是早期的版本,可能會有些許出入)。

內聯彙編代碼可以使用 C/C++ 變量和函數,因此它能非常容易地整合到 C/C++ 代碼中。它能做一些對於單獨使用 C/C++ 來說非常笨重或不可能完成的任務。

一、 優點

使用內聯彙編可以在 C/C++ 代碼中嵌入彙編語言指令,而且不需要額外的彙編和連接步驟。在 Visual C++ 中,內聯彙編是內置的編譯器,因此不需要配置諸如 MASM 一類的獨立彙編工具。這裡,我們就以 Visual Studio .NET 2003 為背景,介紹在 Visual C++ 中使用內聯匯的相關知識(如果是早期的版本,可能會有些許出入)。

內聯彙編代碼可以使用 C/C++ 變量和函數,因此它能非常容易地整合到 C/C++ 代碼中。它能做一些對於單獨使用 C/C++ 來說非常笨重或不可能完成的任務。

內聯彙編的用途包括:

使用彙編語言編寫特定的函數;

編寫對速度要求非常較高的代碼;

在設備驅動程序中直接訪問硬件;

編寫 naked 函數的初始化和結束代碼。

二、 關鍵字

使用內聯彙編要用到 __asm 關鍵字,它可以出現在任何允許 C/C++ 語句出現的地方。我們來看一些例子:

簡單的 __asm 塊:

__asm

{

MOV AL, 2

MOV DX, 0xD007

OUT AL, DX

}

在每條彙編指令之前加 __asm 關鍵字:

__asm MOV AL, 2

__asm MOV DX, 0xD007

__asm OUT AL, DX

因為 __asm 關鍵字是語句分隔符,所以可以把多條彙編指令放在同一行:

__asm MOV AL, 2 __asm MOV DX, 0xD007 __asm OUT AL, DX

顯然,第一種方法與 C/C++ 的風格很一致,並且把彙編代碼和 C/C++ 代碼清楚地分開,還避免了重複輸入 __asm 關鍵字,因此推薦使用第一種方法。

不像在 C/C++ 中的”{ }”,__asm 塊的”{ }”不會影響 C/C++ 變量的作用範圍。同時,__asm 塊可以嵌套,而且嵌套也不會影響變量的作用範圍。

為了與低版本的 Visual C++ 兼容,_asm 和 __asm 具有相同的意義。另外,Visual C++ 支持標準 C++ 的 asm 關鍵字,但是它不會生成任何指令,它的作用僅限於使編譯器不會出現編譯錯誤。要使用內聯彙編,必須使用 __asm 而不是 asm 關鍵字。

三、 彙編語言

1. 指令集

內聯彙編支持 Intel Pentium 4 和 AMD Athlon 的所有指令。更多其它處理器的指令可以通過 _EMIT 偽指令來創建(_EMIT 偽指令說明見下文)。

2. MASM 表達式

在內聯彙編代碼中,可以使用所有的 MASM 表達式(MASM 表達式是指用來計算一個數值或一個地址的操作符和操作數的組合)。

3. 數據指示符和操作符

雖然 __asm 塊中允許使用 C/C++ 的數據類型和對象,但它不能使用 MASM 指示符和操作符來定義數據對象。這裡特別指出,__asm 塊中不允許 MASM 中的定義指示符(DB、DW、DD、DQ、DT 和 DF),也不允許使用 DUP 和 THIS 操作符。MASM 中的結構和記錄也不再有效,內聯彙編不接受 STRUC、RECORD、WIDTH 或者 MASK。

4. EVEN 和 ALIGN 指示符

儘管內聯彙編不支持大多數 MASM 指示符,但它支持 EVEN 和 ALIGN。當需要的時候,這些指示符在彙編代碼裡面加入 NOP 指令(空操作)使標號對齊到特定邊界。這樣可以使某些處理器取指令時具有更高的效率。

5. MASM 宏指示符

內聯彙編不是宏彙編,不能使用 MASM 宏指示符(MACRO、REPT、IRC、IRP 和 ENDM)和宏操作符(、!、、% 和 .TYPE)。

6. 段

必須使用寄存器而不是名稱來指明段(段名稱”_TEXT”是無效的)。並且,段跨越必須顯式地說明,如 ES:[EBX]。

7. 類型和變量大小

在內聯彙編中,可以用 LENGTH、SIZE 和 TYPE 來獲取 C/C++ 變量和類型的大大小。

* LENGTH 操作符用來取得 C/C++ 中數組的元素個數(如果不是一個數組,則結果為 1)。

* SIZE 操作符可以獲取 C/C++ 變量的大小(一個變量的大小是 LENGTH 和 TYPE 的乘積)。

* TYPE 操作符可以返回 C/C++ 類型和變量的大小(如果變量是一個數組,它得到的是數組中單個元素的大小)。

例如,程序中定義了一個 8 維的整數型變量:

int iArray[8];

下面是 C 和彙編表達式中得到的 iArray 及其元素的相關值:

__asm C Size

LENGTH iArray sizeof(iArray)/sizeof(iArray[0]) 8

SIZE iArray sizeof(iArray) 32

TYPE iArray sizeof(iArray[0]) 4

8. 注釋

內聯彙編中可以使用彙編語言的注釋,即”;”。例如:

__asm MOV EAX, OFFSET pbBuff ; Load address of pbBuff

因為 C/C++ 宏將會展開到一個邏輯行中,為了避免在宏中使用彙編語言注釋帶來的混亂,內聯彙編也允許使用 C/C++ 風格的注釋。

9. _EMIT 偽指令

_EMIT 偽指令相當於 MASM 中的 DB,但是 _EMIT 一次只能在當前代碼段(.text 段)中定義一個字節。例如:

__asm

{

JMP _CodeLabel

_EMIT 0x00 ; 定義混合在代碼段的數據

_EMIT 0x01

_CodeLabel: ; 這裡是代碼

_EMIT 0x90 ; NOP指令

}

10. 寄存器使用

一般來說,不能假定某個寄存器在 __asm 塊開始的時候有已知的值。寄存器的值將不能保證會從 __asm 塊保留到另外一個 __asm 塊中。

如果一個函數聲明為 __fastcall 調用方式,則其參數將通過寄存器而不是堆棧來傳遞。這將會使 __asm 塊產生問題,因為函數無法被告知哪個參數在哪個寄存器中。如果函數接收了 EAX 中的參數並立即儲存一個值到 EAX 中的話,原來的參數將丟失掉。另外,在所有聲明為 __fastcall 的函數中,ECX 寄存器是必須一直保留的。為了避免以上的衝突,包含 __asm 塊的函數不要聲明為 __fastcall 調用方式。

提示:如果使用 EAX、EBX、ECX、EDX、ESI 和 EDI 寄存器,你不需要保存它。但如果你用到了 DS、SS、SP、BP 和標誌寄存器,那就應該用 PUSH 保存這些寄存器。

提示:如果程序中改變了用於 STD 和 CLD 的方向標誌,必須將其恢復到原來的值。

四、 使用 C/C++ 元素

1. 可用的 C/C++ 元素

C/C++ 與彙編語言可以混合使用,在內聯彙編中可以使用 C/C++ 變量以及很多其它的 C/C++ 元素,包括:

符號,包括標號、變量和函數名;

常量,包括符號常量和枚舉型成員;

宏定義和預處理指示符;

注釋,包括”/**/”和”//”;

類型名,包括所有 MASM 中合法的類型;

typedef 名稱,通常使用 PTR 和 TYPE 操作符,或者使用指定的的結構或枚舉成員。

在內聯彙編中,可以使用 C/C++ 或彙編語言的基數計數法。例如,0x100 和 100H 是相等的。

2. 操作符使用

內聯彙編中不能使用諸如””一類的 C/C++ 操作符。但是,C/C++ 和 MASM 共有的操作符(比如”*”和”[]”操作符),都被認為是彙編語言的操作符,是可以使用的。舉個例子:

int iArray[10];

__asm MOV iArray[6], BX ; Store BX at iArray + 6 (Not scaled)

iArray[6] = 0; // Store 0 at iArray+12 (Scaled)

提示:在內聯彙編中,可以使用 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++ 符號使用

在 __asm 塊中可以引用所有在作用範圍內的 C/C++ 符號,包括變量名稱、函數名稱和標號。但是不能訪問 C++ 類的成員函數。

下面是在內聯彙編中使用 C/C++ 符號的一些限制:

每條彙編語句只能包含一個 C/C++ 符號。在一條彙編指令中,多個符號只能出現在 LENGTH、TYPE 或 SIZE 表達式中。

在 __asm 塊中引用函數必須先聲明。否則,編譯器將不能區別 __asm 塊中的函數名和標號。

在 __asm 塊中不能使用對於 MASM 來說是保留字的 C/C++ 符號(不區分大小寫)。MASM 保留字包含指令名稱(如 PUSH)和寄存器名稱(如 ESI)等。

在 __asm 塊中不能識別結構和聯合標籤。

4. 訪問 C/C++ 中的數據

內聯彙編的一個非常大的方便之處是它可以使用名稱來引用 C/C++ 變量。例如,如果 C/C++ 變量 iVar 在作用範圍內:

__asm MOV EAX, iVar ; Stores the value of iVar in EAX

如果 C/C++ 中的類、結構或者枚舉成員具有唯一的名稱,則在 __asm 塊中可以只通過成員名稱來訪問(省略”.”操作符之前的變量名或 typedef 名稱)。然而,如果成員不是唯一的,你必須在”.”操作符之前加上變量名或 typedef 名稱。例如,下面的兩個結構都具有 SameName 這個成員變量:

struct FIRST_TYPE

{

char *pszWeasel;

int SameName;

};

struct SECOND_TYPE

{

int iWonton;

long SameName;

};

如果按下面方式聲明變量:

struct FIRST_TYPE ftTest;

struct SECOND_TYPE stTemp;

那麼,所有引用 SameName 成員的地方都必須使用變量名,因為 SameName 不是唯一的。另外,由於上面的 pszWeasel 變量具有唯一的名稱,你可以僅僅使用它的成員名稱來引用它:

__asm

{

MOV EBX, OFFSET ftTest

MOV ECX, [EBX]ftTest.SameName ; 必須使用”ftTest”

MOV ESI, [EBX]. pszWeasel ; 可以省略”ftTest”

}

提示:省略變量名僅僅是為了書寫代碼方便,生成的彙編指令還是一樣的。

5. 用內聯彙編寫函數

如果用內聯彙編寫函數的話,要傳遞參數和返回一個值都是非常容易的。看下面的例子,比較一下用獨立彙編和內聯彙編寫的函數:

; 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++ 函數一般用堆棧來傳遞參數,所以上面的函數中需要通過堆棧位置來訪問它的參數(在 MASM 或其它一些彙編工具中,也允許通過名稱來訪問堆棧參數和局部堆棧變量)。

下面的程序是使用內聯彙編寫的:

// PowerC.c

#include

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

}

使用內聯彙編寫的 GetPowerC 函數可以通過參數名稱來引用它的參數。由於 GetPowerC 函數沒有執行 C 的 return 語句,所以編譯器會給出一個警告信息,我們可以通過 #pragma warning 禁止生成這個警告。

內聯彙編的其中一個用途是編寫 naked 函數的初始化和結束代碼。對於一般的函數,編譯器會自動幫我們生成函數的初始化(構建參數指針和分配局部變量等)和結束代碼(平衡堆棧和返回一個值等)。使用內聯彙編,我們可以自己編寫乾乾淨淨的函數。當然,此時我們必須自己動手做一些有關函數初始化和掃尾的工作。例如:

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. 調用 C/C++ 函數

內聯彙編中調用聲明為 __cdecl 方式(默認)的 C/C++ 函數必須由調用者清除參數堆棧,下面是一個調用 C/C++ 函數例子:

#include

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 個參數在堆棧中,調用函數之後要調整堆棧

ADD ESP, 12

}

}

提示:參數是按從右往左的順序壓入堆棧的。

如果調用 __stdcall 方式的函數,則不需要自己清除堆棧。因為這種函數的返回指令是 RET n,會自動清除堆棧。大多數 Windows API 函數均為 __stdcall 調用方式(僅除 wsprintf 等幾個之外),下面是一個調用 MessageBox 函數的例子:

#include

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] ; 注意這裡不是 CALL MessageBox,而是調用重定位過的函數地址

}

}

提示:可以不受限制地訪問 C++ 成員變量,但是不能訪問 C++ 的成員函數。

7. 定義 __asm 塊為 C/C++ 宏

使用 C/C++ 宏可以方便地把彙編代碼插入到源代碼中。但是這其中需要額外地注意,因為宏將會擴展到一個邏輯行中。

為了不會出現問題,請按以下規則編寫宏:

使用花括號把 __asm 塊包圍住;

把 __asm 關鍵字放在每條彙編指令之前;

使用經典 C 風格的注釋(”/* comment */”),不要使用彙編風格的注釋(”; comment”)或單行的 C/C++ 注釋(”// comment”);

舉個例子,下面定義了一個簡單的宏:

#define PORTIO __asm \

/* Port output */ \

{ \

__asm MOV AL, 2 \

__asm MOV DX, 0xD007 \

__asm OUT DX, AL \

}

乍一看來,後面的三個 __asm 關鍵字好像是多餘的。其實它們是需要的,因為宏將被擴展到一個單行中:

__asm /* Port output */ { __asm MOV AL, 2 __asm MOV DX, 0xD007 __asm OUT DX, AL }

從擴展後的代碼中可以看出,第三個和第四個 __asm 關鍵字是必須的(作為語句分隔符)。在 __asm 塊中,只有 __asm 關鍵字和換行符會被認為是語句分隔符,又因為定義為宏的一個語句塊會被認為是一個邏輯行,所以必須在每條指令之前使用 __asm 關鍵字。

括號也是需要的,如果省略了它,編譯器將不知道彙編代碼在哪裡結束,__asm 塊後面的 C/C++ 語句看起來會被認為是彙編指令。

同樣是由於宏展開的原因,彙編風格的注釋(”; comment”)和單行的 C/C++ 注釋(”// commen”)也可能會出現錯誤。為了避免這些錯誤,在定義 __asm 塊為宏時請使用經典 C 風格的注釋(”/* comment */”)。

和 C/C++ 宏一樣 __asm 塊寫的宏也可以擁有參數。和 C/C++ 宏不一樣的是,__asm 宏不能返回一個值,因此,不能使用這種宏作為 C/C++ 表達式。

不要不加選擇地調用這種類型的宏。比如,在聲明為 __fastcall 的函數中調用彙編語言宏可能會導致不可預料的結果(請參看前文的說明)。

8. 轉跳

可以在 C/C++ 裡面使用 goto 轉跳到 __asm 塊中的標號處,也可以在 __asm 塊中轉跳到 __asm 塊裡面或外面的標號處。__asm 塊內的標號是不區分大小寫的(指令、指示符等也是不區分大小寫的)。例如:

void MyFunction()

{

goto C_Dest; /* 正確 */

goto c_dest; /* 錯誤 */

goto A_Dest; /* 正確 */

goto a_dest; /* 正確 */

__asm

{

JMP C_Dest ; 正確

JMP c_dest ; 錯誤

JMP A_Dest ; 正確

JMP a_dest ; 正確

a_dest: ; __asm 標號

}

C_Dest: /* C/C++ 標號 */

return;

}

不要使用函數名稱當作標號,否則將轉跳到函數中執行,而不是標號處。例如,由於 exit 是 C/C++ 的函數,下面的轉跳將不會到 exit 標號處:

; 錯誤:使用函數名作為標號

JNE exit

.

.

.

exit:

.

.

.

美元符號”$”用於指定當前指令位置,常用於條件跳轉中,例如:

JNE $+5 ; 下面這條指令的長度是 5 個字節

JMP _Label

NOP ; $+5,轉跳到了這裡

.

.

.

_Label:

.

.

.

五、在 Visual C++ 工程中使用獨立彙編

內聯彙編代碼不易於移植,如果你的程序打算在不同類型的機器(比如 x86 和 Alpha)上運行,你可能需要在不同的模塊中使用特定的機器代碼。這時候你可以使用 MASM(Microsoft Macro Assembler),因為 MASM 支持更多方便的宏指令和數據指示符。

這裡簡單介紹一下在 Visual Studio .NET 2003 中調用 MASM 編譯獨立彙編文件的步驟。

在 Visual C++ 工程中,添加按 MASM 的要求編寫的 .asm 文件。在解決方案資源管理器中,右擊這個文件,選擇”屬性”菜單項,在屬性對話框中,點擊”自定義生成步驟”,設置如下項目:

命令行:ML.exe /nologo /c /coff “-Fo$(IntDir)\$(InputName).obj” “$(InputPath)”

輸出:$(IntDir)\$(InputName).obj

如果要生成調試信息,可以在命令行中加入”/Zi”參數,還可以根據需要生成 .lst 和 .sbr 文件。

如果要在彙編文件中調用 Windows API,可以從網上下載 MASM32 包(包含了 MASM 彙編工具、非常完整的 Windows API 頭文件/庫文件、實用宏以及大量的 Win32 彙編例子等)。相應地,應該在命令行中加入”/I X:\MASM32\INCLUDE”參數指定 Windows API 彙編頭文件(.inc)的路徑。MASM32 的主頁是:,裡面可以下載最新版本的 MASM32 包。

在c語言(C++或G++)中如何嵌入彙編

今天有點時間,重新改下了下,為避免因編譯器和平台實現而出現的問題,我寫了三個版本,分別是windows下vc6.0,windows下mingw和cygwin和linux下的gcc/g++。

vc6.0:

#include stdio.h

const char* input = “%d”;

const char* output = “%d\n”;

int n;

int main()

{

__asm

{

lea eax, n

push eax

push input

loopx:

call scanf

cmp eax, 1

jne end

mov ecx, n

jecxz end

dec ecx

push ecx

push output

call printf

add esp, 8

jmp loopx

end:

add esp, 8

}

return 0;

}

mingw/cygwin:

#include stdio.h

const char* input = “%d”;

const char* output = “%d\n”;

int n;

int main()

{

__asm__

(

“loop: \n”

“pushl $_n \n”

“pushl _input \n”

“call _scanf \n”

“addl $8, %esp \n”

“cmpl $1, %eax \n”

“jne end \n”

“movl _n, %ecx \n”

“jecxz end \n”

“decl %ecx \n”

“pushl %ecx \n”

“pushl _output \n”

“call _printf \n”

“addl $8, %esp \n”

“jmp loop \n”

“end:”

);

return 0;

}

linux gcc/g++:

#include stdio.h

const char* input = “%d”;

const char* output = “%d\n”;

int n;

int main()

{

__asm__

(

“pushl $n \n”

“pushl input \n”

“loop: \n”

“call scanf \n”

“cmp $1, %eax \n”

“jne end \n”

“movl n, %ecx \n”

“jecxz end \n”

“decl %ecx \n”

“pushl %ecx \n”

“pushl output \n”

“call printf \n”

“addl $8, %esp \n”

“jmp loop \n”

“end: \n”

“addl $8, %esp \n”);

return 0;

}

如何把彙編程序嵌入到C語言中

不同編譯器嵌入彙編的方式不一樣,具體如下:

一、Turbo

C ,

也就是所說的TC。

1、使用預處理程序的偽指令#asm和#endasm,#asm用來開始一個彙編程序塊,而#endasm指令用於該塊的結束。

參考代碼:

int mul(int a, int b)

{

/*彙編開始*/

#asm

mov ax,word ptr 8[bp]

imul ax word ptr 10[bp]

#endasm

/*彙編結束。*/

}

2、使用asm語句:

格式:asm彙編語句

參考代碼:

int mul(int a, int b)

{

asm mov ax,word ptr 8[bp]

asm imul ax word ptr 10[bp]

/*

每個asm對應一句彙編

注意結尾不需要分號

*/

}

二、VC++/VS

格式:

__asm

彙編指令

[

;

]

__asm

{

彙編指令

}

[

;

]

asm前面是兩條下劃線,後面的方括號內容表示分號可有可無。

使用方法:

1、一條一條地用:

__asm mov al, 2

__asm mov dx, 0xD007

__asm out dx, al

每行一條彙編,

可以有分號,也可以沒有。

2、組成一塊地用:

__asm {

mov al, 2

mov dx, 0xD007

out dx, al

}

整體作為一個彙編代碼塊。

3、也可以將多條彙編寫在一行:

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

三、GNU

GCC

GCC對彙編的支持是最豐富的,簡單介紹如下:

1、

用到的關鍵字:

“__asm__”

表示後面的代碼為內嵌彙編,“asm”是“__asm__”的別名。

“__volatile__” 表示編譯器不要優化代碼,後面的指令保留原樣,“volatile”是它的別名。

括號裡面是彙編指令。

內嵌彙編語法如下:

__asm__(

彙編語句模板:

輸出部分:

輸入部分:

破壞描述部分)

一個簡單的彙編模板:

int a=10,b;

asm(“movl %1, %%eax;

movl %%eax, %0;”

:”=r”(b) /*輸出部*/

:”r”(a) /*輸入部*/

:”%eax” /*毀壞部*/

);

表示C語言里的“b=a;”。

裡邊r表示使用任意寄存器,%0、%1表示使用兩個寄存器,一般只能%0~%9共十個操作數,按輸入輸出部變量出現順序進行映射。

寄存器用兩個百分號,是因為使用了%0%1這些數字使百分號有了特殊意義,所以在操作數出現的寄存器必須用雙百分表示。

毀壞部裡邊的%eax表示eax寄存器在彙編代碼塊執行過程中會被改寫,在執行前要保護好,這是提交給編譯器決定的。

PIC單片機c語言中如何嵌套彙編

3樓的方法是用keil開發51單片機時候潛入彙編的 方法,對於pic單片機來說,不能這楊編譯。因為KEIL不能編譯pic單片機的C語言和彙編語言,必須用MPLAB+PICC或者MPLAB+ mc編譯器 。

一般pic12、16系列的8位中低端單片機的編譯器潛入彙編是用 _asm(” 彙編單句語句 “);

如果要輸入一大段彙編語句,則用:

#asm

N條彙編語句

#endasm

PIC c語言編程 內嵌彙編 報錯提示未定義

我記得PIC C裡面要內嵌彙編的話應該使用“#asm…#endasm”的寫法,而不是_asm。你試試#asm吧

原創文章,作者:STOHV,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/331193.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
STOHV的頭像STOHV
上一篇 2025-01-16 15:47
下一篇 2025-01-16 15:47

相關推薦

  • AES加密解密算法的C語言實現

    AES(Advanced Encryption Standard)是一種對稱加密算法,可用於對數據進行加密和解密。在本篇文章中,我們將介紹C語言中如何實現AES算法,並對實現過程進…

    編程 2025-04-29
  • 學習Python對學習C語言有幫助嗎?

    Python和C語言是兩種非常受歡迎的編程語言,在程序開發中都扮演着非常重要的角色。那麼,學習Python對學習C語言有幫助嗎?答案是肯定的。在本文中,我們將從多個角度探討Pyth…

    編程 2025-04-29
  • Python被稱為膠水語言

    Python作為一種跨平台的解釋性高級語言,最大的特點是被稱為”膠水語言”。 一、簡單易學 Python的語法簡單易學,更加人性化,這使得它成為了初學者的入…

    編程 2025-04-29
  • OpenJudge答案1.6的C語言實現

    本文將從多個方面詳細闡述OpenJudge答案1.6在C語言中的實現方法,幫助初學者更好地學習和理解。 一、需求概述 OpenJudge答案1.6的要求是,輸入兩個整數a和b,輸出…

    編程 2025-04-29
  • Python按位運算符和C語言

    本文將從多個方面詳細闡述Python按位運算符和C語言的相關內容,並給出相應的代碼示例。 一、概述 Python是一種動態的、面向對象的編程語言,其按位運算符是用於按位操作的運算符…

    編程 2025-04-29
  • Python語言由荷蘭人為中心的全能編程開發工程師

    Python語言是一種高級語言,很多編程開發工程師都喜歡使用Python語言進行開發。Python語言的創始人是荷蘭人Guido van Rossum,他在1989年聖誕節期間開始…

    編程 2025-04-28
  • Python語言設計基礎第2版PDF

    Python語言設計基礎第2版PDF是一本介紹Python編程語言的經典教材。本篇文章將從多個方面對該教材進行詳細的闡述和介紹。 一、基礎知識 本教材中介紹了Python編程語言的…

    編程 2025-04-28
  • Python語言實現人名最多數統計

    本文將從幾個方面詳細介紹Python語言實現人名最多數統計的方法和應用。 一、Python實現人名最多數統計的基礎 1、首先,我們需要了解Python語言的一些基礎知識,如列表、字…

    編程 2025-04-28
  • Python作為中心語言,在編程中取代C語言的優勢和挑戰

    Python一直以其簡單易懂的語法和高效的編碼環境而著名。然而,它最近的發展趨勢表明Python的使用範圍已經從腳本語言擴展到了從Web應用到機器學習等廣泛的開發領域。與此同時,C…

    編程 2025-04-28
  • Python基礎語言

    Python作為一種高級編程語言擁有簡潔優雅的語法。在本文中,我們將從多個方面探究Python基礎語言的特點以及使用技巧。 一、數據類型 Python基礎數據類型包括整數、浮點數、…

    編程 2025-04-28

發表回復

登錄後才能評論