c语言内嵌汇编函数 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. 类型和变量大小