程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 關於內聯匯編的幾個技巧

關於內聯匯編的幾個技巧

編輯:關於C++

有時我們的程序需要一些很高的執行效率或者執行系統底層的功能模塊,這些關鍵的部分我們可以采用內聯匯編直接插入匯編指令來達到我們的要求,以下是幾個技巧與大家共同探討.

1.內聯匯編嵌入VC語句:

在VC中內聯匯編非常方便,只需要按照如下格式

__asm{

//匯編語句

}

請看如下示例代碼

void CAlcmemDlg::OnButton3()
{
  DWORD d=(m_size*1024*1024)/sizeof(DWORD);
  DWORD*p=(DWORD*)m_p;
  DWORD s;
  m_pr.SetMin(0);
  m_pr.SetMax((float)d);
  m_pr.SetEnabled(TRUE);
  if(NULL!=m_p){
    __asm{
        mov ecx,d
        mov eax,0
L:        mov edx,DWORD ptr p
        mov [edx+eax],1  //隨便寫入數據,此處寫入1
        inc eax
        mov s,eax
        pushad
    }
    m_pr.SetValue((float)s);
    __asm{
        popad
        loop L
    }
  }
}

請注意示例代碼中兩個__asm塊中的pushad 和 popad 語句,pushad保存了寄存器環境,popad恢復了寄存器環境,使得m_pr.SetValue((float)s);語句對寄存器的影響被抵銷,你還可以調用其他任何語句。但建議是盡量少打斷內聯匯編塊,以減少運行時來回倒騰寄存器環境的時間。筆者的測試是,當刪除m_pr.SetValue((float)s);並且合並兩個__asm塊,同時刪除pushad,和popad後,速度明顯提高。可見這種打斷通常是得不償失。

通常要保存的寄存器環境還有Flags寄存器等,這些視具體情況而定。

2.自由使用FPU,MMX等指令void CAlcmemDlg::OnButton4()
{
  float f_t=.132;
  float f_s=0;
  __asm{
    fld f_s
    fld f_s
    fld f_s
    fld f_t
    fadd f_t
    fst f_t
//    fadd fs
  }
}

可以利用設置斷點的方法來觀察FPU寄存器的情況,通常你用VC寫的代碼,不會被編譯為引用特殊指令集的代碼,雖然微軟號稱編譯器支持這些指令。所以你必須用內聯匯編方法來調用這些指令以優化程序,充分利用資源。示例中的代碼調用了FPU處理器的指令,使操作浮點數的能力被充分發揮。但當然你還可以調用3DNOW!指令,SSE,SSE2等指令,但筆者沒有試過,如果你有什麼新的發現,還望賜教,再此先謝了!

總的來說內聯匯編提高了速度,尤其是游戲編程,更應該努力使用內聯匯編,把CPU充分搾干,但壞處就是有些低端的機器無法運行,兼容性差。同時微軟又號稱,編譯器不會去優化你寫的匯編碼,他只是簡單的翻譯為等價的機器碼,優化的事情交給你自己來完成,所以你不但得是C++高手,同時還得是匯編高手。不過據我所知這種人十有八九是黑客。我是不鼓勵你成為那類人的,撰寫此文只為拋磚引玉。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved