如何在Visual Studio项目中正确添加汇编代码 .

引用注明>> 【作者:张佩】【镜像:www.yiiyee.cn/blog】

 

1.      问题描述

 

在以往的编程经历中,本人最常使用的汇编代码是__asm {int 3}。它可以在我的代码中插入一个软件断点。如果没有一个连接到当前程序的调试器,则程序将停止在这行语句处无法继续执行。

上面的这种方式称为高级语言和汇编语言混编。当我用得正爽的时候,迎头碰到了64位平台这员猛将。它大手一张,挑出一张禁令通知单:在64位编程中,高级语言和汇编混编将再也不被支持!兄弟我不禁暗暗垂泪,因为当我固执而行的时候,若干恶心的编译错误赫然出现在我的面前:

[html] view plaincopy

  1. 1>test.cpp(98):error C4235: nonstandard extension used : '__asm' keyword not supported on thisarchitecture  
  2. 1>test.cpp(98):warning C4091: '' : ignored on left of 'int' when no variable is declared  
  3. 1>test.cpp(98):error C2143: syntax error : missing ';' before 'constant'  
 
  1. 1>test.cpp(98):error C4235: nonstandard extension used : '__asm' keyword not supported on thisarchitecture

  2. 1>test.cpp(98):warning C4091: '' : ignored on left of 'int' when no variable is declared

  3. 1>test.cpp(98):error C2143: syntax error : missing ';' before 'constant'

 上面的几行所示的并非什么惊天动地的大错误,意思非常简单:当前架构不支持__asm关键字。

既然被踢出了体制外,我们要想生存,就必须得另谋出路。

 

 2.      使用.asm文件

 

在64位平台上,我们遇到了翩然而至的.asm文件。在和她共舞的过程中,下面几个步骤必须遵守:

 

  1. 使用.asm文件包含汇编代码;.asm文件以关键字.CODE开始,关键字END结束
  2. 所有的汇编代码以函数方式组织在一起,一个典型的函数声明如下:

 

 

 

[cpp] view plaincopy

  1. FunName PROC  
  2.     // 此处包含汇编指令   
  3. FunName ENDP  
 
  1. FunName PROC

  2. // 此处包含汇编指令

  3. FunName ENDP

这里面有两个关键字分别表示函数的开始和结束:PROC和ENDP。我们看一个简单的包含中断指令的函数应当怎么写。我们假设一个.asm文件中仅有一个函数实现,下面是一个.asm汇编源文件的全部内容:

[cpp] view plaincopy

  1. //   
  2. // FILE: test.asm   
  3. // Description: 汇编源文件。当前文件仅在x64平台上编译,并不包含于x86平台,可通过设置源文件的属性实现。   
  4. //    
  5.   
  6. .CODE // 文件开始   
  7.   
  8. // 函数原型: void Int_3()   
  9. // 函数描述:函数实现中断指令,没有输入/输出参数,也没有返回值   
  10. Int_3 PROC  
  11.        int 3 // 中断指令   
  12.        ret   // 函数返回指令   
  13. Int_3 ENDP  
  14.   
  15. END  // 文件结束  
 
  1. //

  2. // FILE: test.asm

  3. // Description: 汇编源文件。当前文件仅在x64平台上编译,并不包含于x86平台,可通过设置源文件的属性实现。

  4. //

  5.  
  6. .CODE // 文件开始

  7.  
  8. // 函数原型: void Int_3()

  9. // 函数描述:函数实现中断指令,没有输入/输出参数,也没有返回值

  10. Int_3 PROC

  11. int 3 // 中断指令

  12. ret // 函数返回指令

  13. Int_3 ENDP

  14.  
  15. END // 文件结束

这个文件名为test.asm,文件包含名为Int_3的汇编函数,函数本身仅有两行代码:中断指令,返回指令。

 

 3.      X86与X64的兼容

 

现在澄清一下状况:

 

  1. 在X86平台上,我们应该使用混编方式执行汇编指令;
  2. 在X64平台上,我们应该使用.asm添加汇编函数。

 

 

 

为了让一段包含汇编指令的代码能够同时在X86和X64平台上编译通过,我们要有办法让编译器自己判断硬件平台。编译器提供了名为_M_AMD64的宏,只有在X64平台上,这个宏才是被定义的。所以我们可以用类似下面的语法进行编程:

[cpp] view plaincopy

  1. #ifdef _M_AMD64   
  2.   // 这是x64平台   
  3. #else   
  4.   // 这是x86平台   
  5. #endif  
 
  1. #ifdef _M_AMD64

  2. // 这是x64平台

  3. #else

  4. // 这是x86平台

  5. #endif

实际上,大多数软件都不使用_M_AMD64宏,而是使用在windows.h中定义的另一个表达同一含义的名为_AMD64_的宏。所以上文的另一种写法如下:

 

[cpp] view plaincopy

  1. #include <windows.h>   
  2.   
  3. #ifdef _AMD64_   
  4.   // 这是x64平台   
  5. #else   
  6.   // 这是x86平台   
  7. #endif  
 
  1. #include <windows.h>

  2.  
  3. #ifdef _AMD64_

  4. // 这是x64平台

  5. #else

  6. // 这是x86平台

  7. #endif

如果我们只想在程序中添加一个软中断指令,则完整的实现示例如下:

 

[cpp] view plaincopy

  1. #include <windows.h>   
  2.   
  3. extern "C" void Int_3();  
  4.   
  5. int _tmain()  
  6. {  
  7. #ifdef _AMD64_   
  8.    printf("这是x64平台,使用.asm汇编文件中定义的中断函数\n");  
  9.    Int_3();  
  10. #else   
  11.    printf("这是x86平台,使用__asm混编方式插入中断指令\n");  
  12.    __asm int 3;  
  13. #endif   
  14.   
  15.   return 0;  
  16. }  
 
  1. #include <windows.h>

  2.  
  3. extern "C" void Int_3();

  4.  
  5. int _tmain()

  6. {

  7. #ifdef _AMD64_

  8. printf("这是x64平台,使用.asm汇编文件中定义的中断函数\n");

  9. Int_3();

  10. #else

  11. printf("这是x86平台,使用__asm混编方式插入中断指令\n");

  12. __asm int 3;

  13. #endif

  14.  
  15. return 0;

  16. }

 

4.      Visual Studio编译

 

将.asm文件添加到项目中后,如果不做任何操作即直接编译,我们会惊奇地发现.asm文件被编译器无视了(未被编译)。为弄清个中缘由,请在.asm文件上右击并选择属性,在弹出的属性对话框中,你是否看到如下设置?

 

由于这个文件的"项类型"被默认设置为“不参与生成”,所以在编译的时候,编译器就不会带上它。不晓得这一点在新的Visual Studio里面会不会有改正。这时候各位也不要慌了手脚,Visual Studio看上去对.asm这个灰头土脸的家伙有点不客气,觉得它好面生,所以有什么活动都不愿意带上它。没有关系,让我们想办法来让它们熟悉起来吧。

 

  1. 首先,确保你当前的平台是x64平台。切记不要对x86平台下的.asm文件做任何修改,因为.asm文件在x86平台上是无法编译的(目前为止,据我所知)。
  2. 其次,请确保“从生成中排除”项的值是“否”。
  3. 第三,让我们点击"项类型"的下标箭头,会看到如下所示的众多可选项:

 

 

 

第一个选项“C/C++编译器”,是用来编译.C/.cpp文件的,如果点击一个.cpp文件看到的就会是它被默认选中。但汇编文件不能使用C/C++编译器,读者不信可以试一试,一定有乱七八糟的编译错误秀出来。正确的做法是选择“自定义生成工具”项,点击“应用”后左列将出现名为“自定义生成工具”的子项,如下图所示:

在右列面板中,我们有一些设置需要添加进去,上图中已由红色方框标出。

 

  1. 首先在“命令行”项中,我们应当输入指定的编译语句:ml64 /c %(fileName).asm。这条命令的意思是使用ml64.exe.asm文件进行编译,这里面的宏%(FileName)用来代指当前文件(test.asm)。命令行中的ml64乃指Ml64.exe编译程序,它在Visual Studio的默认执行路径中。把这条执行语句直接放在控制台里面执行,一样是能够通过的。
  2. 在“输出”项中,我们设定输出文件为:%(fileName).obj。即编译后所生成的中间文件,而宏%(filename)含义如上。

 

 

 

确定并退出属性对话框后,再次尝试,会发现x86和x64平台下的编译都能够成功了。我们通过上述方法,成功地在C/C++项目中添加汇编指令,并能够在32/64位平台上顺利编译通过。虽然我还没有亲自试验,但相信相同的方法也能够使用于.net等其他编程语言。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/380983.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

eclipse代码发布到服务器(Tomcat)出现乱码现象解决方法

我们只需写两行代码就可以解决问题了 //设置response查询的码表 response.setCharacterEncoding(“UTF-8”); //通过一个头Content - Type 告知客户端使用何种码表 response.setHeader(“Content-Type”, “text/html;charsetUTF-8”); response.getWriter().write(“…

多叉树的前序遍历_二叉树的非递归遍历的思考

封面图来自wikipedia1 简介二叉树的深度优先遍历&#xff08;前序遍历、中序遍历、后序遍历&#xff09;是一个比较基本的操作。如果使用递归的做法&#xff0c;很容易写出相应的程序&#xff1b;而如果使用非递归的做法&#xff0c;虽然也能写出相应的代码&#xff0c;但是由于…

delphi中Label中文显示不全的问题解决办法

有时候把Label的AutoSize属性设置为True&#xff0c;当窗体显示的时候&#xff0c;Label中的内容可能会显示不完全&#xff0c;只能把AutoSize设置为False&#xff0c; 把Label调整成能显示出内容的大小。还有一种更简单的解决方法。把Form的Font属性进行如下设置&#xff1a;字…

vs+vm双机调试

基础&#xff1a; VS2017安装成功 wdk10 注意事项&#xff1a; 关闭 、主机 客户机 防火墙 、 互相ping都能ping通。 一、具体操作步骤 工具安装就不说了&#xff0c;不会的百度一下。只说一下一些关键的地方。 1、安装好虚拟机后&#xff0c;给虚拟机增加一个串口设备。具体…

为什么要返回softmax_为什么softmax搭配cross entropy是解决分类问题的通用方案?

众所周知&#xff0c;softmaxcross entropy是在线性模型、神经网络等模型中解决分类问题的通用方案&#xff0c;但是为什么选择这种方案呢&#xff1f;它相对于其他方案有什么优势&#xff1f;笔者一直也困惑不解&#xff0c;最近浏览了一些资料&#xff0c;有一些小小心得&…

servlet下载文件(注意文件名字必须是英文)

直接将代码放在servlet下&#xff0c;把文件名字换成自己要下载的就行 文件要放在WEGCONTEN下 //获得下载文件的名称String filename request.getParameter("filename");//要下载的这个文件的类型 -----客户端根据mime类型区分别response.setContentType(this.getS…

2010.07.13_19:30

又是地铁中&#xff0c;音乐在响&#xff0c;离目的地一半&#xff0c;又一天上班结束。转载于:https://www.cnblogs.com/sunxi2003/archive/2010/07/13/1776724.html

焊接空间臂_焊接烟尘净化器设备哪种好

焊接烟尘净化器设备采用滤筒除尘器&#xff0c;焊接烟尘净化器用于焊接、切割、打磨等工序中产生烟尘和粉尘的净化以及对稀有金属、贵重物料的回收等&#xff0c;可净化大量悬浮在空气中对人体有害的细小金属颗粒。具有净化效率高、噪声低、使用灵活、占地面积小等特点。 适用于…

关于Tomcat文件下载中文名乱码现象

//获得下载文件的名称 String filename request.getParameter(“filename”); //解决获得中文参数的乱码 filename new String(filename.getBytes(“ISO8859-1”),“UTF-8”); //获得请求头的User-Agent String agent request.getHeader(“User-Agent”); //根据不同的浏览器…

【摘录】C语言中利用 strtok函数进行字符串分割

C语言不像Java,Php之类的高级语言&#xff0c;对象中直接封装了字符串的处理函数。C语言中进行普通的字符串处理也经常会让我们焦头烂额……不过好在C语言 中还是提供了像strtok这样功能强大的字符串处理函数&#xff0c;可以帮我们实现部分需要的功能。下面我们介绍一下strtok…

x86汇编指令大全

X86和X87汇编指令大全&#xff08;有注释&#xff09; ---------- 一、数据传输指令 ---------------------------------------------------- 它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据. 1. 通用数据传送指令. MOV 传送字或字节. MOVSX …

woe分析_Python数据分析—apply函数

在对海量数据进行分析的过程中&#xff0c;我们可能要把文本型的数据处理成数值型的数据&#xff0c;方便放到模型中进行使用。也可能需要把数值型的数据分段进行处理&#xff0c;比如变量的woe化。而这些操作都可以借助python中的apply函数进行处理。今天介绍数据分析的第四课…

树莓派3b安装ubuntu mate(在有显示器前提下看)

树莓派安装&#xff1a; 准备材料 tf卡&#xff08;建议16G&#xff09;数据线树莓派win32烧录软件 &#xff0c;百度云链接&#xff1a;链接&#xff1a;https://pan.baidu.com/s/16Dq2XrqeJScUO_DxHRIz_g 提取码&#xff1a;kfkbubtuntu mate系统&#xff08;建议不要下ubu…

vb逆向常用函数

1) 数据类型转换: a) __vbaI2Str 将一个字符串转为8 位&#xff08;1个字节&#xff09;的数值形式(范围在 0 至 255 之间) 或2 个字节的数值形式(范围在 -32,768 到 32,767 之间)。 b)__vbaI4Str 将一个字符串转为长整型(4个字节)的数值形式(范围从-2,147,483,6482,147,…

回车转换成Tab

<script language"javascript" for"document" event"onkeydown"> if(event.keyCode13 && event.srcElement.type!’button’ && event.srcElement.type!’submit’ && event.srcElement.type!’reset’ &&am…

打包mac应用_把网址链接打包成电脑软件的制作方法

前言&#xff1a;学习一下把web页面打包成运行在桌面的应用, 并支持win / mac / linux 等平台, 记一下使用过程, 有需要的大(同)佬(学)可以玩玩~第一步 – 安装 node.jsnode.js下载地址&#xff1a;http://nodejs.cn/download/下载 Windows 安装包 (.msi) 和 Windows 二进制文件…

用eclipse往mysql插入中文出现乱码解决方法

用eclipse往mysql插入中文出现乱码的解决方法 注&#xff1a;我用的是c3p0结合DButils操作数据库 在要从页面获得数据的代码上面设置&#xff1a; request.setCharacterEncoding("UTF-8"); 在c3p0-config文件里设置&#xff1a; <property name"jdbcUrl&…

c++ 中extern C 及#ifdef __cplusplus的作用

浅析extern “C”的作用 关于extern “C”的作用和意思&#xff0c;网上资料已经有很多了&#xff08;我也参考了几篇&#xff09;&#xff0c;不过我还是觉得有必要自己总结一下&#xff0c;毕竟“好记性不如烂笔头”嘛~~ 到C标准函数库的头文件里看看&#xff0c;一般会经常看…

对多个WCF服务进行统一的连接测试

先看下面的代码&#xff1a;代码代码 BasicHttpBinding myBinding newBasicHttpBinding(); EndpointAddress myEndpoint newEndpointAddress(endAddress); ChannelFactory<IMyService>myChannelFactory newChannelFactory<IMyService>(myBinding,my…

宜昌宝塔河项目_宜昌城区首个垃圾分类定时定点投放点启用 厨余垃圾破袋投放...

伍家岗区宝联社区黄龙小区的垃圾分类定时定点投放点启用。(市环境卫生管理处供图)(记者郑璐、通讯员陈赞)1月1日&#xff0c;宜昌城区首个垃圾分类定时定点投放点在伍家岗区宝塔河街办宝联社区黄龙小区正式启用。该投放点每天开放5小时&#xff0c;上午7&#xff1a;00-9:30&am…