c51 汇编调用c函数

c51 汇编调用c函数,第1张

c51 汇编调用c函数:一般都是C调用汇编的,倒是反过来了,在C函数中,如果要严格时序或者精确 *** 作的要求,某一段会用汇编来写,不管是C调用汇编,还是汇编调用C。

我的程序KEIL编译器,EXTRN CODE(_Send_CRC)的第一个国家Send_CRC C函数编译加上调用_LCALL _Send_CRC如果您要成相应的数据,然后使用变量在C,XDATA代码。

一般形式:

函数名(实参表列);如果是调用无参函数,则"实参表列"可以没有,但括弧不能省略。如果实参表列包含多个实参,则个参数间用逗号隔开。实参与形参的个数应相等,类型应一致。

实参与形参按顺序对应,一一传递数据。但应说明,如果实参表列包括多个实参,对实参求值的顺序并不是确定的,有的系统按自左至右顺序求实参的值,有的系统则按自右至左顺序

首先写个H文件,把汇编的函数申明在里面

例如:

extern bit plus(iu8 d_dat,iu8 s_dat,u8 len);

然后,建立ASM文件,例如toolasm

先指定存储区

PR_plusTOOL SEGMENT CODE

PR固定的,然后是函数名前+下划线,TOOL 是这个asm的名字,CODE是存储区

然后向外申明函数

PUBLIC _plus

最后是函数体

RSEG PR_plusTOOL

_plus:

USING 0

。。。。

ret

参数传递,R7是第一个参数,R6是第二个。。。,如果不是char ,或参数是指针,那么占用多个Rn,

例如:

这个函数中,d_dat是R7,R6;s_dat是R5,R4;len是R3

C语言与汇编语言混合编程应遵守的规则

ARM编程中使用的C语言是标准C语言,ARM的开发环境实际上就是嵌入了一个C语言的集成开发环境,只不过这个开发环境与ARM的硬件紧密相关。

在使用C语言时,要用到和汇编语言的混合编程。若汇编代码较为简洁,则可使用直接内嵌汇编的方法;否则要将汇编程序以文件的形式加入到项目中,按照ATPCS(ARM/Thumb过程调用标准,ARM/Thumb Procedure Call Standard)的规定与C程序相互调用与访问。

在C程序和ARM汇编程序之间相互调用时必须遵守ATPCS规则。ATPCS规定了一些子程序间调用的基本规则,哪寄存器的使用规则,堆栈的使用规则和参数的传递规则等。

1)寄存器的使用规则

子程序之间通过寄存器r0~r3来传递参数,当参数个数多于4个时,使用堆栈来传递参数。此时r0~r3可记作A1~A4。

在子程序中,使用寄存器r4~r11保存局部变量。因此当进行子程序调用时要注意对这些寄存器的保存和恢复。此时r4~r11可记作V1~V8。

寄存器r12用于保存堆栈指针SP,当子程序返回时使用该寄存器出栈,记作IP。

寄存器r13用作堆栈指针,记作SP。寄存器r14称为链接寄存器,记作LR。该寄存器用于保存子程序的返回地址。

寄存器r15称为程序计数器,记作PC。

2)堆栈的使用规则

ATPCS规定堆栈采用满递减类型(FD,Full Descending),即堆栈通过减小存储器地址而向下增长,堆栈指针指向内含有效数据项的最低地址。

3)参数的传递规则

整数参数的前4个使用r0~r3传递,其他参数使用堆栈传递;浮点参数使用编号最小且能够满足需要的一组连续的FP寄存器传递参数。

子程序的返回结果为一个32位整数时,通过r0返回;返回结果为一个64位整数时,通过r0和r1返回;依此类推。结果为浮点数时,通过浮点运算部件的寄存器F0、D0或者S0返回。

2、汇编程序调用C程序的方法

汇编程序的书写要遵循ATPCS规则,以保证程序调用时参数正确传递。在汇编程序中调用C程序的方法为:首先在汇编程序中使用IMPORT伪指令事先声明将要调用的C语言函数;然后通过BL指令来调用C函数。

例如在一个C源文件中定义了如下求和函数:

int add(int x,int y){

return(x+y);

}

调用add()函数的汇编程序结构如下:

IMPORT add ;声明要调用的C函数

……

MOV r0,1

MOV r1,2

BL add ;调用C函数add

……

当进行函数调用时,使用r0和r1实现参数传递,返回结果由r0带回。函数调用结束后,r0的值变成3。

3、C程序调用汇编程序的方法

C程序调用汇编程序时,汇编程序的书写也要遵循ATPCS规则,以保证程序调用时参数正确传递。在C程序中调用汇编子程序的方法为:首先在汇编程序中使用EXPORT伪指令声明被调用的子程序,表示该子程序将在其他文件中被调用;然后在C程序中使用extern关键字声明要调用的汇编子程序为外部函数。

例如在一个汇编源文件中定义了如下求和函数:

EXPORT add ;声明add子程序将被外部函数调用

……

add ;求和子程序add

ADD r0,r0,r1

MOV pc,lr

……

在一个C程序的main()函数中对add汇编子程序进行了调用:

extern int add (int x,int y); //声明add为外部函数

void main(){

int a=1,b=2,c;

c=add(a,b); //调用add子程序

……

}

当main()函数调用add汇编子程序时,变量a、b的值会给了r0和r1,返回结果由r0带回,并赋值给变量c。函数调用结束后,变量c的值变成3。

4、C程序中内嵌汇编语句

在C语言中内嵌汇编语句可以实现一些高级语言不能实现或者不容易实现的功能。对于时间紧迫的功能也可以通过在C语言中内嵌汇编语句来实现。内嵌的汇编器支持大部分ARM指令和Thumb指令,但是不支持诸如直接修改PC实现跳转的底层功能,也不能直接引用C语言中的变量。

嵌入式汇编语句在形式上独立定义的函数体,其语法格式为:

__asm

{

指令[;指令]

……

[指令]

}

其中“__asm”为内嵌汇编语句的关键字,需要特别注意的是前面有两个下划线。指令之间用分号分隔,如果一条指令占据多行,除最后一行外都要使用连字符“\”。

5、基于ARM的C语言与汇编语言混合编程举例

下面给出了一个向串口不断发送0x55的例子:

该工程的启动代码使用汇编语言编写,向串口发送数据使用C语言实现,下面是启动代码的整体框架:

……

IMPORT Main

AREA Init,CODE,READONLY;

ENTRY

……

BL Main ;跳转到Main()函数处的C/C++程序

……

END ;标识汇编程序结束

下面是使用C语言编写的主函数:

#include "\inc\configh" //将有关硬件定义的头文件包含进来

unsigned char data; //定义全局变量

void main(void){

Target_Init(); //对目标板的硬件初始化

Delay(10); //延时

data=0x55; //给全局变量赋值

while(1) {

Uart_Printf("%x",data); //向串口送数

Delay(10);

}

}

在 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]ftTestSameName ; 必须使用"ftTest"

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

}

提示:省略变量名仅仅是为了书写代码方便,生成的汇编指令还是一样的。

5 用内联汇编写函数

如果用内联汇编写函数的话,要传递参数和返回一个值都是非常容易的。看下面的例子,比较一下用独立汇编和内联汇编写的函数:

; PowerAsmasm

; 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 或其它一些汇编工具中,也允许通过名称来访问堆栈参数和局部堆栈变量)。

下面的程序是使用内联汇编写的:

// PowerCc

#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 文件。在解决方案资源管理器中,右击这个文件,选择"属性"菜单项,在属性对话框中,点击"自定义生成步骤",设置如下项目:

命令行:MLexe /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 的主页是:http://wwwmasm32com,里面可以下载最新版本的 MASM32 包。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/12188920.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-21
下一篇2023-05-21

发表评论

登录后才能评论

评论列表(0条)

    保存