VC內聯ASM彙編學習筆記

來源:互聯網
上載者:User

轉載:http://old.blog.edu.cn/user2/44558/archives/2006/1209858.shtml
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中的函數:

下面是一個例子:

#include 

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塊中的代碼.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.