在Visual C++中使用内联汇编
2010-01-10 09:37:22 来源:WEB开发网内联汇编能通过变两名直接引用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:;
- ››使用脚本恢复WinXP系统的用户登录密码
- ››使用phpMyadmin创建数据库及独立数据库帐号
- ››使用Zend Framework框架中的Zend_Mail模块发送邮件...
- ››使用cout标准输出如何控制小数点后位数
- ››使用nofollow标签做SEO的技巧
- ››使用 WebSphere Message Broker 的 WebSphere Tra...
- ››使用SQL Server事件探查器做应用程序的性能分析
- ››使用SQL Server事件探查器分析死锁原因
- ››使用纯文本文件打造WCF服务
- ››Visual Studio自定义调试窗体两个小技巧
- ››使用 Dojo 开发定制 Business Space 小部件,第 4...
- ››使用 ADDRESS 与 INDIRECT函数查询信息
更多精彩
赞助商链接