WEB开发网
开发学院软件开发汇编语言 在Visual C++中使用内联汇编 阅读

在Visual C++中使用内联汇编

 2010-01-10 09:37:22 来源:WEB开发网   
核心提示:内联汇编能通过变两名直接引用C/C++的变量,__asm块中可以引用任何符号,在Visual C++中使用内联汇编(3),包括变量名,如果C/C++中的类、结构或者枚举成员具有唯一的名称,如下所示:;错误: 使用函数名作为标号JNE exit,,如果在"."操作符之前不指定变量或者typedef名称

内联汇编能通过变两名直接引用C/C++的变量。__asm块中可以引用任何符号,包括变量名。

如果C/C++中的类、结构或者枚举成员具有唯一的名称,如果在"."操作符之前不指定变量或者typedef名称,则__asm块中只能引用成员名称。然而,如果成员不是唯一的,你必须在"."操作符之前加上变量名或typedef名称。例如,下面的两个结构都具有same_name这个成员变量:

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成员的地方都必须使用变量名,因为same_name不是唯一的。另外,上面的weasel变量具有唯一的名称,你可以仅仅使用它的成员名称来引用它:

__asm
  {
  MOV EBX,
  OFFSET hal
MOV ECX, [EBX]hal.same_name ; 必须使用 ’hal’
MOV ESI, [EBX].weasel ; 可以省略 ’hal’
}

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

可以不受限制地访问C++成员变量,但是不能调用C++的成员函数。

五、寄存器使用

一般来说,在__asm块开始的时候,寄存器是空的,不能在两个__asm之间保存寄存器的值。(这是MSDN上说的,我在实际使用时发现,好像并不是这样。不过它是说"一般",我是特殊:))

如果一个函数被声明成了__fastcall,则其参数将放在寄存器中,这将给寄存器的管理带来问题。所以,如果要将一个函数声明成__fastcall,必须保存ECX寄存器。为了避免以上的冲突,在声明为__fastcall的函数中不要有__asm块。如果用了/Gr编译选项(它全局的变成__fastcall),将每个函数声明成__cdecl或者__stdcall,这个属性告诉编译器用传统的C方法。

如果使用EAX、EBX、ECX、EDX、ESI和EDI寄存器,你不需要保存它;但如果你用到了DS、 SS、SP、BP和标志寄存器,那就应该PUSH保存这些寄存器。

如果程序中改变了用于STD和CLD的方向标志,你必须将其恢复到原来的值。

六、转跳

可以在C里面使用goto调到__asm块中的标号处,也可以在__asm块中转跳到__asm块里面和外面的标号处。__asm块内的标号是不区分大小写的(指令、指示符等也是不区分大小写的)。例:

void func()
  {
  goto C_Dest;/* 合法 */
  goto c_dest;/* 错误 */
  goto A_Dest;/* 合法 */
  goto a_dest;/* 合法 */
  __asm
  {
  JMP C_Dest; 合法
  JMP c_dest; MSDN上说合法,但是我在VS.NET中编译,认为这样不合法
  JMP A_Dest; 合法
  JMP a_dest; 合法
  a_dest: ; __asm 标号
  }
  C_Dest: /* C的标号 */
  return;
  }

不要使用函数名称当作标号,否则将使其跳到函数执行而不是标号处。如下所示:;

错误: 使用函数名作为标号
  JNE exit
  。
  。
  。
  exit:;

上一页  1 2 3 4 5  下一页

Tags:Visual 使用 内联

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接