原创 如何用VC编译汇编程序

2007-2-28 21:13 7116 8 8 分类: MCU/ 嵌入式

                   MASM6.14从傻瓜到入门

  最近有网友向我询问如何使用MASM6.14,其实我也不是很懂,只是对一些常用的功能有所了解。对于一些常见的问题,这一点点可怜的知识还是勉强可以解决的。所以本文只是从最浅显的方面谈一下MASM6.14的用法,只是能让读者入门而已。本文将分成几个部分来叙述。


1.ML的参数问题
  在编译的时候主要使用的是ML.EXE,因此,我们的重点将集中在这个程序上。 ML.EXE的使用格式如下:
     ML [ /options ] filelist [ /link linkoptions ]

  下面简单解释一下一些常用的编译选项,因为绝大多数参数我也没有用过,所以,我不能保证解释的正确性,如果你发现了什么错误,欢迎来信告诉我。

 /AT  :允许小模式
 /Bl  :指定链接器
 /c  :只编译,不链接
 /Cp  :保留用户标识符的大小写
 /Cu  :所有标识符映射为大写
 /Cx  :用public或者extrn引用的标志符保留大小写
 /coff  :产生coff格式的目标文件
 /F   :设置堆栈长度
 /Fe  :命名可执行程序
 /Fo  :命名目标文件
 /FPi :对80x87指令进行软件仿真
 /G :使用Pascal,C或者stdcall调用
 /I :添加包含文件的路径
 /WX :视警告为错误
 /W :设置警告级别
 /Zd :在调试信息中添加行标号
 /Zf :使所有符号变为PUBLIC类型
 /Zi :在调试信息中添加符号信息
 /Zm :与MASM5.10兼容
 /Zp[n] :设置结构的对齐方式
 /Zs :只进行语法检测


  上述内容只是从帮助文件中翻译过来的,很不全面,也不一定正确,有兴趣的朋友可以看一下原文。其实绝大多数参数是根本用不上的,我很少使用汇编去编写一个完整的程序,通常是使用高级语言编译器来辅助的。因为现在的高级语言都有着非常强大的编译和调试的功能,所以汇编语言的编译器只要提供一些必要的功能就可以了。


 
2..xmm和.k3d
  现在一些单指令多数据技术十分流行,其中尤以intel公司的Streaming SIMD Extensions 和AMD公司的3DNow为最。MASM6.14可以支持这两种指令集。

  在程序文件首加入.xmm表示需要编译器提供对Streaming SIMD Extensions指令集的支持。如果你想学习SSE指令可以看一下《全面优化Pentium III》一文,那里面对所有SSE指令作了简单的解释。

  在程序文件首加入.k3d表示需要3DNow的支持。不过使用3DNow指令没有必要依赖MASM,你可以在VC中直接使用。虽然VC并不支持3DNow指令的内联汇编,但是AMD的工程师是非常聪明的,他们想出了一种很好的办法,可以让你在VC 中用类似于内联汇编的方法使用3DNow指令。他们的方法是使用带参数的宏,直接在代码中内嵌3DNow指令的二进制代码。你可以从本站下载AMD 3DNow的 SDK,里面有一些必要的头文件和库文件。
3.符号的命名规范
  完全使用汇编语言编写程序是不切实际的,也是根本没有必要的。大概只有两种情况需要用到汇编:要求很高的执行效率或者需要执行系统底层的功能。因此,我们在多数情况下还是要用高级语言的,只是在关键的部分使用汇编语言,这就要求我们必须知道如何将高级语言和汇编语言结合起来。如果使用内联汇编那就简单的多了,只要加入asm关键字就可以了。不过,有些指令是不被内联汇编所支持的,这就使得我们不得不编写真正的汇编程序文件。汇编语言和高级语言的命名规范是不太一样的,必须正确命名汇编文件里的标识符,这样才能够在高级语言中正常调用。下面简要介绍一些常见的命名原则:
(1)为程序段命名
  在C语言中,代码段都是以“_TEXT”作为段名的,数据段是用“_DATA”作为段名的。这条规则在Pascal中也是适用的。下面是一个例子:
     _TEXT segment public use32 'CODE'

     _TEXT ends

  这段程序定义了一个代码段,use32告诉编译器生成32位代码。
(2)为标识符命名
  C语言在编译以后,为所有的标识符添加了一条下划线作为前缀。如果你想在汇编语言中引用在C程序中定义的变量或函数,就必须也加上一条下划线。如果你使用的是C++编译器,那么还要注意一点,你一定要使用C链接才能使标识符符合上述命名规范。下面就是一个例子:
  //这是在C语言中的定义方法

  extern "C"
  {
       int hello;
  }


  ;;这是在汇编语言中进行引用

     extrn _hello
     ;...其它的代码
     ;............
     mov     _hello,   0

(3)函数调用
  变量的命名还是比较简单的,为函数命名就要考虑更多的问题了。不仅仅是要添加下划线,还要考虑调用规范,有时甚至要弄清楚各个编译器的命名原则。下名列出一些常用的调用规范(这些规范只适用于C链接):
  __cdecl
  这种调用规范比较简单,只要在变量名前面加上下划线就可以了。而且,这种调用方式在任何编译器中都是相同的。详细规则如下:
  参数从右向左入栈

  由调用者管理参数出栈

  添加下划线作为前缀

  __stdcall
  很多Windows API都是使用这种调用方式,它比较节省空间。
  参数从右向左入栈

  由被调用者负责参数出栈

  添加下划线作为前缀,加@n作为后缀,其中“n”为参数的字节数。(如果使用C++Builder,则无需添加前后缀,直接使用)

  __fastcall
  这是利用寄存器传输参数的调用方式。
  如果使用VC,那么前两个参数传给ECX和EDX寄存器,剩下的从右向左入栈;如果使用C++Builder,那么前三个双字依次通过EAX,EDX和ECX寄存器传送,其它的从右向左入栈。

  由被调用者负责参数出栈

  添加"@"作为前缀,加"@n"作为后缀,其中“n”为参数的字节数。(如果使用C++Builder,则无需添加后缀,只需“@”作为前缀)

  __msfastcall
  这是Inprise公司为了和微软的调用规范兼容而采用的一个特别的关键字。实际上,没有必要在VC中使用__fastcall,以我的个人经验,这种方式在VC中没有得到很好的优化,执行效率反而会降低。


 
在高级语言中使用MASM6.14
  我们可以使用一些方便的办法来把汇编语言的编译器和高级语言的开发环境有效地结合起来,每次编译都使用命令行是不明智的。
  在VC中的使用方法
  VC提供了一些支持,可以自动的编译汇编文件,你可以按照以下步骤进行:
  在菜单中选择“Project | Settings...”
  选中指定的汇编文件(单击即可)
  选中Custom Build页
  在Commands中输入:
  如果是DEBUG模式,则输入:
  e:\masm32\bin\ml /c /coff /Zi /FoDEBUG\$(InputName).obj $(InputPath)

  如果是RELEASE模式,则输入:
  e:\masm32\bin\ml /c /coff /FoRELEASE\$(InputName).obj $(InputPath)

  在Outputs中输入:
  如果是DEBUG模式,则输入:
  DEBUG\$(InputName).obj

  如果是RELEASE模式,则输入:
  RELEASE\$(InputName).obj

  如果你的没有把masm安装在E盘,则要作相应的修改。
  相应的参数还有必要再解释一下:
  “/c”表示只编译不链接。“/coff”表示生成coff格式的目标文件,这是在 VC中使用的文件格式。“/Zi”表示需要产生符号信息,便于调试。


 
  在C++Builder中的使用方法
  我没有找到好方法!C++Builder使用它自带的TASM,不过该编译器不支持最新的指令集。如果你想在C++Builder中使用MASM,建议你用批处理命令进行编译,然后把目标文件添加到工程文件里来。
以上内容,仅供参考,如有叙述不当之处,希望各位网友不吝赐教。

以上内容为转载: http://dwbclz.myetang.com/articles/masmhelp/index.html

我做了些补充说明

对于 console 程序的汇编,
也就是链接选项中有 /SUBSYSTEM:CONSOLE 的
使用 Win32 Console Application 来编译汇编

1 新建一个 Win32 Console Application 的工程
2 加入汇编文件
3 在 project -> settings 选中指定的汇编文件(单击即可),选中Custom Build页
在 Commands 中和 Outputs 中分别输入:

对 DEBUG

g:\masm32\bin\ml /c /coff /Zi /FoDEBUG\$(InputName).obj $(InputPath)

DEBUG\$(InputName).obj

对 RELEASE

g:\masm32\bin\ml /c /coff /FoRELEASE\$(InputName).obj $(InputPath)

RELEASE\$(InputName).obj


注意我的masm32是安在g:\下的,这里根据不同情况可能需要更改。

对于 sdk 程序的汇编,
也就是链接选项中有 /SUBSYSTEM:WINDOWS 的
使用 Win32 Application 来编译汇编
1 新建一个 Win32 Application 的工程
其他步骤同console

注意,如果想使用vc的debug来进行源码级的调试,必须有编译选项 /Zi 。
另外,还可以用vc的makefile来建工程,然后自己写makefile,
进行编译和调试,不过比用上面的方法麻烦。

  以上内容亦为转载:http://jiurl.cosoft.org.cn/forum/viewtopic.php?t=54

  以下内容:为Crige本人在应用过程中发现的应注意的问题:

  1)“g:\masm32\bin\ml /c /coff /Zi /FoDEBUG\$(InputName).obj $(InputPath) DEBUG\$(InputName).obj”中的字符串“$(InputName)“与”InputPath“应保持原样,而不
应改动;其也可通过设定来自动添加,如点击Driectory按钮选Input选项即可自动输入$(InputName),
点File按钮选Input Path选项即可自动输入$(InputPath);

  2)在编译时提示找不到"windows.inc"等头文件及库文件的解决方法:
打开菜单Tools/Options 转到Directories选项卡,在Show directories for中选Include files,点添加(就是那个框型的图标),选好路径如“e:\masm32\inlcude",然后通过点击向上箭头按钮,把“e:\masm32\inlcude"移到最上面来,其实这一项不移也可以,编绎器也会找到的,因为VC用的头文件与MASM用的头文件的扩展名不同啊,同理,Show directories for中选Libries files,点添加(就是那个框型的图标),选好路径如“e:\masm32\lib",然后通过点击向上箭头按钮,把“e:\masm32\lib"移到最上面来,这一项我建议还是移到最前面好,因为编绎器首先会链接MASM的库文件,否则的话,就会先链接VC的库文件了,这样虽然编绎也可通过,生成的OBJ文件我没有比较过是否相同,哈哈,经过测试对生成EXE文件没什么影响啊。

  3)接下来就是LINK了,在VC中是不能LINK这个文件的,可至DOS下,使用LINK来链接。
   可通过两种方式,一种是直接用LINK /subsystem:windows参数,另一种是使用MAKEFILE文件的方式均可。但是不管是用哪种方式,都要先运行MASM环境设置批处理文件,我的是Masm32.bat。

  4) 很多网友会碰到的一个问题是:运行环境变量设置批处理文件时会碰到系统提示“Out of environment space”的问题,解决方法如下:
   编辑config.sys文件,在文件最后一行,添加如下:
   SHELL="c:"\command.com c:\ /P /E:2048
   一行,重启即可。注:如果2048缓冲区还不够大的话,可改为4096、8192等。

  5)最后,真诚的推荐,直接应用AOGO的Masm for EditPlus sierial 0004代替上述方法,实现编辑、编译、链接一条龙服务啊,呵呵。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
8
关闭 站长推荐上一条 /3 下一条