zoukankan      html  css  js  c++  java
  • VC内联ASM汇编学习笔记【转】

    目的:学习在VC中进行ASM汇编语言程序设计的方法,以提高底层应用能力.

    由于在VC中进行汇编不需要额外的编译器和联接器,且可以处理VC中不能处理的一些事情,而且可以使用在C中的变量,所以,非常方便.但是它并不支持所有的MASM宏和数据指示符.

    下面的三种方法基本上都可以使用在VC中:

    __asm
    {
    mov  al,  2
    mov  dx,  0xD007
    out  al,  dx
    }


    __asm  mov  al,  2
    __asm  mov  dx,  0xD007
    __asm  out  al,  dx


    __asm  mov  al,  2  __asm  mov  dx,  0xD007  __asm  out  al,  dx


    显然,最好的是第一种.

    _emit相当于MASM中的DB.

    虽然内联汇编可以使用C/C++中的变量,但是它不能够自己定义变量.

    可以使用EVEN和ALIGN.

    不能够使用MASM宏.

    必须使用寄存器来说明段,跨越段必须显式地说明,如ES:[BX].

    在内联汇编中的类型和变量大小:

    我们可以使用LENGTH来取得C/C++中的数组中的元素个数,如果不是一个数组,则结果为一.使用SIZE来取得C/C++中变量的大小,一个变量的大小是LENGTH和TYPE的乘积.TYPE用来取得一个变量的大小,如果是一个数组,它得到的一个数组中的单个元素的大小.

    VC中允许使用MMX指令.

    内联的ASM代码并不易于移植,所以,应当尽量避免.
    在__asm块中可以使用的元素:

    1.符号包括函数名

    2.常数和enum类型

    3.宏和预处理成员

    4.注释

    5.MASM中的类型名

    6.typedef,PTR,TYPE

    寄存器:

    一般来说,在__asm块开始的时候,寄存器是空的.不能在两个__asm之间保存寄存器的值.

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

    不用保存EAX,  EBX,  ECX,  EDX,  ESI,  or  EDI寄存器.但却需要保存DS,  SS,  SP,  BP,  and标志寄存器.

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

    跳转:

    可以使用goto和ASM指定跳到label或__asm以外的程序段中去.例:

    void  func(  void  )
    {
    goto  C_Dest;  /*  Legal:  correct  case  */
    goto  c_dest;  /*  Error:  incorrect  case  */

    goto  A_Dest;  /*  Legal:  correct  case  */
    goto  a_dest;  /*  Legal:  incorrect  case  */

    __asm
    {
    jmp  C_Dest  ;  Legal:  correct  case
    jmp  c_dest  ;  Legal:  incorrect  case

    jmp  A_Dest  ;  Legal:  correct  case
    jmp  a_dest  ;  Legal:  incorrect  case

    a_dest:  ;  __asm  label
    }

    C_Dest:  /*  C  label  */ 
    return;
    }

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

    ;  BAD  TECHNIQUE:  using  library  function  name  as  label
    jne  exit
    .
    .
    .
    exit:
    ;  More  __asm  code  follows

    美元符号$用于指定当前位置,如下所用,常用于条件跳转:

    jne  $+5  ;  next  instruction  is  5  bytes  long
    jmp  farlabel
    ;  $+5
    .
    .
    .
    farlabel:
    调用C中的函数:

    下面是一个例子:

    #i nclude 

    char  format[]  =  "%s  %s\n";
    char  hello[]  =  "Hello";
    char  world[]  =  "world";
    void  main(  void  )
    {
    __asm
    {
    mov  eax,  offset  world
    push  eax
    mov  eax,  offset  hello
    push  eax
    mov  eax,  offset  format
    push  eax
    call  printf
    //clean  up  the  stack  so  that  main  can  exit  cleanly
    //use  the  unused  register  ebx  to  do  the  cleanup
    pop  ebx
    pop  ebx
    pop  ebx
    }
    }


    注意:函数参数是从右向左压栈.

    不能够访问C++中的类成员函数.可以访问extern  "C"函数.

    VC不会优化__asm块中的代码. 
  • 相关阅读:
    spring-schedule
    数字电路
    面试题
    CMOS集成门电路
    TTL特殊门电路
    TTL反相器的外部特性
    TTL集成门电路工作原理和电压传输特性
    半导体器件的开关特性和分立元件门电路
    逻辑函数的公式化减法
    php 获取当前文件名称
  • 原文地址:https://www.cnblogs.com/ahuo/p/1581683.html
Copyright © 2011-2022 走看看