如何在Visual C++中使用汇编语言

时间:2022-02-26 11:50:43
 
如何在Visual C++ 中使用汇编语言
 
 
         今天,可能大多数的程序员都会对汇编语言怀有戒心,认为它是一种非常难理解及使用的语言,要么就认为它是老掉牙了,早就应该被更高级的语言取代。本文就是要消除大家心中的畏惧,其实它并不是很难于运用,正相反,文中还将演示了可极大地降低汇编语言使用难度的MASM,并怎样将它与Visual Studio集成。
 
 
         首先,什么是汇编语言,今天还谈汇编语言有什么意义吗?简单来说,它是处理器的语言,没有比这更低级的语言了(除了那些指令的实际字节值);它的每条命令(mov、add等等)都由宏汇编程序(MASM)直接翻译为处理器执行的“数字”。
         使用汇编语言的最大优势在于速度,这是一种完全原生、未受限制的速度,即使现在的编译器能够对代码进行优化,恐怕这些优化后的代码也难与手工编写、人工优化的汇编代码相抗衡。
         当然了,汇编语言也不是每个地方都适用的,虽然可用汇编语言来编写整个程序,但与C++等今天其他高级语言相比,还是有点过于“自虐”了,就拿今天占绝对数量优势的应用程序来说,C++甚至.NET语言的速度,也是非常令人满意的。
         所以,只有在极其看重速度的场合才适用汇编语言,比如说图形程序,在编写小型、快速寻址大块内存的函数上,汇编语言也是不可战胜的,位图操纵就是一个典型的例子。该说的也说得差不多了,下面来看看怎样使用它。
 
 
         在Visual C++ 中编写汇编代码
         可使用 __asm语句块在Visual C++中编写汇编代码:
 
 
DWORD Function(DWORD dwValue)
{
   __asm
   {
      mov eax, dwValue
      add eax, 100
      mov dwValue, eax
   }
 
   return dwValue;
}
 
 
         在 __asm块中包含了一些汇编指令,C++编译器会把它们直接翻译成机器语言代码。以上代码的意思只是简单地把传递进来的数值加上100。
         在 __asm块中编写一小点汇编代码还是可行的,但是要编写长一点的代码,那就变得单调乏味了,例如,一个“if…else”语句将会像下面这样:
 
 
DWORD Function2(DWORD dwValue1, DWORD dwValue2)
{
   DWORD dwValue3 = 0;
 
#if 0
   if (dwValue1 == dwValue2)
   {
      dwValue3 = 1;
   }
   else
   {
      dwValue3 = 2;
   }
#endif
 
   __asm
   {
      mov eax, dwValue1
 
      ; 此处对值进行比较,是否dwValue1 == dwValue2
      cmp eax, dwValue2
 
      ; 如果不相等,跳到“Else”
      jne Else
 
      mov eax, 1
      jmp EndIf
 
   Else:
      mov eax, 2
 
   EndIf:
      mov dwValue3, eax
   }
 
   return dwValue3;
}
 
 
         如果每个if语句都要这样来写,人都可能要崩溃了。在 __asm块中写汇编代码,就像在记事本或命令行中写C++代码一样,枯燥而乏味,此时可以借助Microsoft Macro Assembler(MASM),它能生成与Visual C++链接器相兼容的 .obj文件,甚至在其中还能包含调试信息。使用了MASM之后,前面的代码就能像下面这样写:
 
 
Function proc dwValue1:DWORD, dwValue2:DWORD
 
   mov eax, dwValue1
 
   .if eax == dwValue2
      mov eax, 1
   .else
      mov eax, 2
   .endif
 
   ret
 
Function endp
 
 
         这样看上去可读性就高多了,下面就来看一下如何添加汇编文件到现有C++工程中,及在C++中如何访问汇编语言编写的函数。
 
 
         添加汇编文件到Visual C++
         以下说明以Visual C++ 6.0为例,其他版本的也类似。首先,需要包含MASM的bin文件夹,在Tools/Options/Projects/Visual C++ Directories中,添加“bin”文件夹,本文中为“C:/MASM32/bin”。
 
  如何在Visual C++中使用汇编语言
 
 
         把这个目录移到最下端,这一点非常重要,因为这个目录中也有一个名为link.exe的链接程序,这样做是为了防止干扰Visual Studio的默认链接器。
 
         现在,创建一个控制台程序。添加一个“test.asm”文件到工程中:在Solution Explorer中右键单击“source files”文件夹,选择Add/New Item。
 
  如何在Visual C++中使用汇编语言
 
 
         输入“test.asm”后回车,现在一个“test.asm”的新文件就打开在你面前了。
         在文件中输入以下代码:
 
 
486
.model flat, stdcall
option casemap :none
 
.code
 
TestProc proc dwValue:DWORD
 
   mov eax, dwValue
   add eax, 100
   ret
 
TestProc endp
 
End
 
 
         代码仍是把传递进来的值加上100,并返回其结果。
         注意:所有的MASM汇编文件都需要包含最前面4行及最后的End,实际代码位于.code与End之间。
 
         现在,设置文件的生成属性,在Debug模式中右键单击文件,并选择“properties”,接着选择“custom build step/general”,并在“command line”中输入以下:
 
ml /c /coff /Zi /Fo"$(OutDir)/$(InputName).asm.obj" "$(InputFileName)"
 
         还要在“Outputs”下输入:$(OutDir)/$(InputName).asm.obj
 
         如下图:
 
  如何在Visual C++中使用汇编语言
 
 
         Release模式与上面基本相同,除了编译行中没有/Zi选项,这个代表“generate debug info”,所以应为:ml /c /coff /Fo"$(OutDir)/$(InputName).asm.obj" "$(InputFileName)"。
 
 
         从C++ 中调用汇编代码
         前面的汇编代码定义一个名为“TestProc”的函数,其接受一个DWORD(32位)的参数,所以在C++中调用之前,需先有一个函数定义。找到main函数的cpp文件,把下面一行添加在#include后面:
 
 
extern "C" unsigned int __stdcall TestProc(unsigned int dwValue);
 
 
在main函数中加入以下代码:
 
int main(int argc, _TCHAR* argv[])
{
   unsigned int dwValue = 100;
   unsigned int dwReturn = TestProc(dwValue);
 
   printf("%d/n", dwReturn);
   getchar();
 
   return 0;
}
 
 
         运行这个程序之后,返回的结果值将会是预期的200,另外,如果在调用TestProc处放置一个断点,就能单步调试这个方法,甚至可在汇编代码中放置断点。
 
 
         看到这,觉得在VC中使用汇编语言不难吧,如果要加快程序的运行速度,或者要执行一些以前想都不敢想的实时任务,现在,可以动手试一下了。