当前位置:编程学习 > 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

            _Cod

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,