sohot的文章

  • Android Studio使用POI读取及修改Word文档(.docx格式)

    一、说明上一篇文章(Android Studio使用POI读取及修改Word文档(.doc格式))使用poi对.doc格式的word文档进行了读取和更改,但很多情况下还需要在word文档中插入图片,这时就需要对.docx格式的word进行操作了。
    二、实现过程2.1 制作文书文书在源代码中可以直接看到,简单说明一下:文书有普通字段、表格、特定位置的图片,又在页眉页脚中加了普通字段和表格,基本满足对于word操作的所有情况。

    2.2 导包还是上篇中poi-3.9压缩资源包中的jar包,对.docx格式文档的操作用到XWPFDocument方法,使用到所有ooxml相关的jar包。

    2.3 build配置这次的build配置有点特殊,特别拿出来截图一下。就像上一篇说的一样,apache的很多配置在安卓是跑不通的,这次导包后,你会遇到方法过多,文件重复,基于jdk1.6以上版本的变异保存等一系列问题,可以按照下面的方法处理。当然不同的android studio版本可能也会有不同的处理方法,可以百度一下。

    权限还是储存权限,直接上代码吧,注解的也很详细。
    2.4 实现源码public class MainActivity extends AppCompatActivity { //创建生成的文件地址 private static final String newPath = "/storage/emulated/0/test.docx"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 0); } Button go = (Button) findViewById(R.id.go); go.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { initData(); } }); } private void initData() { Map<String, Object> map = new HashMap<String, Object>(); map.put("$TITLE$", "标题");//$TITLE$只是个标识符,你也可以用${},[]等等 map.put("$TXT1$", "表格第一行"); map.put("$CONTENT1$", "第一行内容"); map.put("$TXT2$", "表格第二行"); map.put("$CONTENT2$", "第二行内容"); map.put("$CONTENT3$", "页脚中的内容"); map.put("$TXT4$", "页脚表格第一行"); map.put("$CONTENT4$", "页脚第一行内容"); map.put("$TXT5$", "页脚表格第二行"); map.put("$CONTENT5$", "页脚第二行内容"); try { //读取示例文书 InputStream is = getAssets().open("test.docx"); //自定义的XWPFDocument,解决官方版图片不显示问题 CustomXWPFDocument document = new CustomXWPFDocument(is); //读取段落(一般段落,页眉页脚没办法读取) List<XWPFParagraph> listParagraphs = document.getParagraphs(); processParagraphs(listParagraphs, map); //读取页脚 List<XWPFFooter> footerList = document.getFooterList(); processParagraph(footerList, map); //处理表格 Iterator<XWPFTable> it = document.getTablesIterator(); while (it.hasNext()) {//循环操作表格 XWPFTable table = it.next(); List<XWPFTableRow> rows = table.getRows(); for (XWPFTableRow row : rows) {//取得表格的行 List<XWPFTableCell> cells = row.getTableCells(); for (XWPFTableCell cell : cells) {//取得单元格 if ("$IMG$".equals(cell.getText())) { //直接插入图片会在文档的最底端,所以要插在固定位置,要把图片放在表格里 //所以使用判断单元格,并清除单元格放置图片的方式来实现图片定位 cell.removeParagraph(0); XWPFParagraph pargraph = cell.addParagraph(); document.addPictureData(getAssets().open("1.png"), XWPFDocument.PICTURE_TYPE_PNG); document.createPicture(document.getAllPictures().size() - 1, 120, 120, pargraph); } List<XWPFParagraph> paragraphListTable = cell.getParagraphs(); processParagraphs(paragraphListTable, map); } } } FileOutputStream fopts = new FileOutputStream(newPath); document.write(fopts); if (fopts != null) { fopts.close(); } } catch (Exception e) { e.printStackTrace(); } } //处理页脚中的段落,其实就是用方法读取了下页脚中的内容,然后也会当做一般段落处理 private void processParagraph(List<XWPFFooter> footerList, Map<String, Object> map) { if (footerList != null && footerList.size() > 0) { for (XWPFFooter footer : footerList) { //读取一般段落 List<XWPFParagraph> paragraphs = footer.getParagraphs(); processParagraphs(paragraphs, map); //处理表格 List<XWPFTable> tables = footer.getTables(); for (int i = 0; i < tables.size(); i++) { XWPFTable xwpfTable = tables.get(i); List<XWPFTableRow> rows = xwpfTable.getRows(); for (XWPFTableRow row : rows) {//取得表格的行 List<XWPFTableCell> cells = row.getTableCells(); for (XWPFTableCell cell : cells) {//取得单元格 List<XWPFParagraph> paragraphListTable = cell.getParagraphs(); processParagraphs(paragraphListTable, map); } } } } } } //处理段落 public static void processParagraphs(List<XWPFParagraph> paragraphList, Map<String, Object> param) { if (paragraphList != null && paragraphList.size() > 0) { for (XWPFParagraph paragraph : paragraphList) { List<XWPFRun> runs = paragraph.getRuns(); for (XWPFRun run : runs) { String text = run.getText(0); if (text != null) { boolean isSetText = false; for (Map.Entry<String, Object> entry : param.entrySet()) { String key = entry.getKey(); if (text.indexOf(key) != -1) { isSetText = true; Object value = entry.getValue(); if (value instanceof String) {//文本替换 text = text.replace(key, value.toString()); } } } if (isSetText) { run.setText(text, 0); } } } } } }}
    2.5 效果展示
    本文转载自:https://blog.csdn.net/qq_21972583/article/details/82740281
    2  留言 2019-10-08 13:02:23
  • Android Studio使用POI读取及修改Word文档(.doc格式)

    一、前言如果你可爱的项目经理要求安卓端的你来操作word实现各种功能,不要犹豫,直接动之以情晓之以理,因为这本来就是java的poi,安卓虽然源自java,但对于java的很多东西是不支持的,已有的各种jar包也不方便更改,各种报错会搞的你脑阔疼。所以编辑word文档这种事让后台来做要比安卓来做简单的多,但如果实在避免不了,接着,给你代码。
    二、说明本篇不支持word2007版,只支持2003版,也就是只支持.doc格式,不支持.docx格式(想要支持.docx格式请参考“Android Studio使用POI读取及修改Word文档(.docx格式)”)。.doc格式的word文档是不支持图片插入的,因为.doc格式和.docx格式有很大的区别,用到的jar包和方法也不同,如果需要插入图片,请查看下篇对.docx格式word文档的处理。
    三、实现过程3.1 制作文书制作.doc格式的文档,然后导入项目:

    文章展示的文档内容如下:

    3.2 导包用到java poi-3.9中的两个包,完整压缩包点这里下载。然后复制用来编辑.doc文档的两个依赖包,导入libs目录。

    如果提示报错,是因为jar中有重复文件,请看build配置。

    加入外部存储读写权限,以后还需要自行申请,代码中有体现:
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    3.3 实现代码读写过程直接上代码了,一看就懂:
    Button go;//生成文件的所在的地址private static final String newPath = "/storage/emulated/0/hwpfdocument.doc";@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); go = (Button) findViewById(R.id.go); go.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { readWord(); } }); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 0); }}private void readWord() { try { //从assets读取我们的Word模板 InputStream is = getAssets().open("hwpfdocument.doc"); //创建生成的文件路径 File newFile = new File(newPath); //需要修改的字段放入map中 Map<String, String> map = new HashMap<String, String>(); map.put("${TITLE}", "标题"); map.put("${TXT}", "表格第一行"); map.put("${CONTENT}", "内容"); writeDoc(is, newFile, map); } catch (IOException e) { e.printStackTrace(); }}private void writeDoc(InputStream is, File newFile, Map<String, String> map) { try { //使用poi的HWPFDocument方法 HWPFDocument hdt = new HWPFDocument(is); //Range读取word文本内容 Range range = hdt.getOverallRange(); //replaceText替换文本内容 for (Map.Entry<String, String> entry : map.entrySet()) { range.replaceText(entry.getKey(), entry.getValue()); } ByteArrayOutputStream ostream = new ByteArrayOutputStream(); FileOutputStream out = new FileOutputStream(newFile, true); hdt.write(ostream); //输出字节流 out.write(ostream.toByteArray()); out.close(); ostream.close(); Toast.makeText(this, "文书已生成", Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); }}
    3.4 效果展示
    附录关于Apache POI - HWPF和XWPF的说明可以参考这里。
    关于HWPF的API可以参考这里。左上角选择org.apache.poi.hwpf,然后左下角选择hwpfdocument即可。
    本文转载自:https://blog.csdn.net/qq_21972583/article/details/82385940
    1  留言 2019-10-06 11:36:29
  • 内联汇编之64位程序

    背景内联汇编是指在 C/C++ 代码中嵌入的汇编代码,与全部是汇编的汇编源文件不同,它们被嵌入到 C/C++ 的大环境中。内联汇编方式两个作用,一是程序的某些关键代码直接用汇编语言编写,可提高代码的执行效率;二是有些操作无法通过高级语言实现,或者实现起来很困难,必须借助汇编语言达到目的。
    32 位程序和 64 位程序下使用内联汇编的方式,有很大的差别。现在,我们对此分别进行介绍。本篇文章主要介绍的是在 64 位程序中使用内联汇编。
    VS2013中添加并编译 .asm 文件步骤在 64 位程序中,已经不能使用关键字 __asm 来添加汇编代码,而应把汇编代码全部写在 .asm 文件中,然后,再将 .asm 包含到项目中编译链接。现在,我们就先来讲解如何使用 VS2013 添加并编译 .asm 文件的步骤。
    注意,以下演示实现从 x86 模式,即 Win32 模式下开始,如果从 x64 模式开始,在设置 .asm 文件的“自定义生成工具”的时候会卡死或者无反应。从 Win32 模式开始设置后,再新建 x64 模式,并从 Win32 模式复制设置,这样就可以成功对 .asm 文件设置“自定义生成工具”。
    首先,我们在本地上新建一个 .asm 格式的文件 “myasm.asm”之后,右击项目工程并选择“添加” —> “现有项”,然后选择我们新创建的“myasm.asm”文件,添加到工程中:

    然后,我们选中“myasm.asm”文件,并右击选择“属性”:

    在“myasm.asm属性页”中,设置 从生成中排除 为“否”,设置 项类型 为“自定义生成工具”,然后,点击“应用”。这时,在窗口左侧就会生成“自定义生成工具”的扩展栏。如果是从 x64 模式下设置的,在一步,会没有反应或者卡死。所以,一定要从 Win32 模式开始,再创建 x64 模式,并把 Win32 的设置复制到 x64 模式中,便可以解决这个问题。

    接着,我们开始新建 x64 模式,因为我们要开发的是 64 位程序。我们选中项目工程,以此选择 “属性” —> “配置属性” —> “配置管理器” —> “活动解决方案平台”选择“新建”。这时,就会来到“新建解决方案平台”页面。我们选择“x64”,并从 Win32 中复制设置,创建新的项目平台,点击“确定”。这时,就可以使用 x64 模式编译 64 位程序了。

    然后,我们继续对 .asm 文件进行设置,将其包含到项目工程中来编译链接。选中“myasm.asm”文件,右击选择“属性”,来到“myasm.asm”属性页进行设置。在 命令行 中输入“ml64 /c %(fileName).asm”,在 输出 中输入“%(fileName).obj”,其它保持默认即可,点击“确定”即可完成设置。

    经过上述几个步骤,我们成功为 x64 程序添加 .asm 文件并设置包含到项目工程中编译链接。接下来,我们就开始讲解如何在 .asm 文件中写汇编代码了。
    实现原理对于 64 位程序在 .asm 中写代码,需要遵循以下几个规则:

    会变文件 .asm 文件必须以关键字 .CODE 开始,关键字 END 结束,大小写都可以。
    .code ; 此处写汇编指令代码end

    所有的汇编代码以函数方式组织在一起。也就是说,我们要将汇编代码封装成一个个汇编函数。要注意 64 位汇编中的函数声明以及调用约定:
    .code; _MyAdd是汇编函数_MyAdd proc ; 此处写汇编函数的代码_MyAdd endpend
    其中, _MyAsm 是汇编函数的名称,proc 是汇编函数的关键字,endp 是汇编函数的结尾关键字。
    要注意和 32 位汇编函数的区别:32 位汇编函数调用约定 __stdcall,所有参数从右到左依次入栈,通过压栈传递参数。64 位汇编函数的调用约定 __fastcall,前 4 个参数是从左至右依次存放于RCX、RDX、R8、R9寄存器里面,剩下的参数从左至右顺序入栈。
    编码实现myasm.asm.code_MyAdd proc xor rax, rax mov rax, rcx add rax, rdx add rax, r8 add rax, r9 ret_MyAdd endpend
    ASM_64_Test.cppextern "C" ULONGLONG _MyAdd(ULONGLONG a1, ULONGLONG a2, ULONGLONG a3, ULONGLONG a4);int _tmain(int argc, _TCHAR* argv[]){ ULONGLONG a1 = 1; ULONGLONG a2 = 2; ULONGLONG a3 = 3; ULONGLONG a4 = 4; ULONGLONG b = _MyAdd(a1, a2, a3, a4); printf("b=%d\n", b); system("pause"); return 0;}
    程序测试我们直接运行程序,成功显示正确的计算结果:

    然后,我们查看 RAX、RCX、RDX、R8、R9 这 5 个寄存器里的值,和上述我们讲解的相一致:

    总结要特别注意一点就是,如果你使用 VS2013 开发环境,或者你使用其它的开发环境也遇到这样一个问题就是:在 x64 模式下,添加 .asm 文件,并设置在 .asm 属性页 中设置“自定义生成工具”后,界面出现卡死、无反应现象。可以尝试下面的解决方法:

    首先,不要在 x64 模式下面进行设置 .asm 属性页。更换到 x86 模式,即 Win32 模式下,然后再在 .asm 属性页 中设置“自定义生成工具”,这时可以正常设置。
    然后,在在 .asm 属性页 中设置“自定义生成工具”,这时,我们再“新建” x64 的解决方案平台,从 Win32 中复制设置。

    那么,这时,我们就可以在 x64 下正常对“自定义生成工具”进行设置了。
    同时,也要要注意和 32 位汇编函数的区别:32 位汇编函数调用约定 __stdcall,所有参数从右到左依次入栈,通过压栈传递参数。64 位汇编函数的调用约定 __fastcall,前 4 个参数是从左至右依次存放于RCX、RDX、R8、R9寄存器里面,剩下的参数从左至右顺序入栈。
    参考参考自《Windows黑客编程技术详解》一书
    2  留言 2019-01-03 10:50:43
  • 内联汇编之32位程序

    背景内联汇编是指在 C/C++ 代码中嵌入的汇编代码,与全部是汇编的汇编源文件不同,它们被嵌入到 C/C++ 的大环境中。内联汇编方式两个作用,一是程序的某些关键代码直接用汇编语言编写,可提高代码的执行效率;二是有些操作无法通过高级语言实现,或者实现起来很困难,必须借助汇编语言达到目的。
    32 位程序和 64 位程序下使用内联汇编的方式,有很大的差别。现在,我们对此分别进行介绍。本篇文章主要介绍的是在 32 位程序中使用内联汇编。
    实现过程使用内联汇编要用到 __asm 关键字,它可以出现在任何允许 C/C++ 语句出现的地方。对 __asm 关键字的使用有两种方式:

    __asm 块,要添加大括号
    __asm { // 汇编代码 }
    __asm 语句,在每条汇编指令之前加 __asm 关键字
    __asm // 汇编代码

    显然,第一种方法与 C/C++ 的风格很一致,并且把汇编代码和 C/C++ 代码清楚地分开,还避免了重复输入 __asm 关键字,因此推荐使用第一种方法。
    不像在 C/C++ 中的“{ }”,__asm 块的“{ }”不会影响 C/C++ 变量的作用范围。同时,__asm 块可以嵌套,而且嵌套也不会影响变量的作用范围。
    为了与低版本的 Visual C++ 兼容,_asm 和 __asm 具有相同的意义。另外,Visual C++ 支持标准 C++ 的 asm 关键字,但是它不会生成任何指令,它的作用仅限于使编译器不会出现编译错误。要使用内联汇编,必须使用 __asm 而不是 asm 关键字。
    编码实现void MyFunc(char *pszText){ printf("%s\n", pszText);}int _tmain(int argc, _TCHAR* argv[]){ char str1[] = "__asm{ }"; char str2[] = "__asm"; // 32位程序内联汇编 第一种方式 __asm { lea eax, str1 push eax mov eax, MyFunc call eax } // 32位程序内联汇编 第二种方式 __asm lea eax, str2 __asm push eax __asm mov eax, MyFunc __asm call eax system("pause"); return 0;}
    程序测试我们直接运行程序,程序成功显示两行字符串,说明两种方式的内联汇编均使用成功。

    总结在 32 位程序中使用内联汇编比较方便,就两种形式,一种是有大括号的:
    __asm{ // 汇编代码}
    另一种是没有大括号的:
    __asm // 汇编代码
    这两种方式是等价的,大家可以根据自己的程序需要,自行选择使用哪种方式即可。
    参考参考自《Windows黑客编程技术详解》一书
    2  留言 2019-01-03 10:50:01
  • 内联汇编之64位程序

    背景内联汇编是指在 C/C++ 代码中嵌入的汇编代码,与全部是汇编的汇编源文件不同,它们被嵌入到 C/C++ 的大环境中。内联汇编方式两个作用,一是程序的某些关键代码直接用汇编语言编写,可提高代码的执行效率;二是有些操作无法通过高级语言实现,或者实现起来很困难,必须借助汇编语言达到目的。
    32 位程序和 64 位程序下使用内联汇编的方式,有很大的差别。现在,我们对此分别进行介绍。本篇文章主要介绍的是在 64 位程序中使用内联汇编。
    VS2013中添加并编译 .asm 文件步骤在 64 位程序中,已经不能使用关键字 __asm 来添加汇编代码,而应把汇编代码全部写在 .asm 文件中,然后,再将 .asm 包含到项目中编译链接。现在,我们就先来讲解如何使用 VS2013 添加并编译 .asm 文件的步骤。
    注意,以下演示实现从 x86 模式,即 Win32 模式下开始,如果从 x64 模式开始,在设置 .asm 文件的“自定义生成工具”的时候会卡死或者无反应。从 Win32 模式开始设置后,再新建 x64 模式,并从 Win32 模式复制设置,这样就可以成功对 .asm 文件设置“自定义生成工具”。
    首先,我们在本地上新建一个 .asm 格式的文件 “myasm.asm”之后,右击项目工程并选择“添加” —> “现有项”,然后选择我们新创建的“myasm.asm”文件,添加到工程中:

    然后,我们选中“myasm.asm”文件,并右击选择“属性”:

    在“myasm.asm属性页”中,设置 从生成中排除 为“否”,设置 项类型 为“自定义生成工具”,然后,点击“应用”。这时,在窗口左侧就会生成“自定义生成工具”的扩展栏。如果是从 x64 模式下设置的,在一步,会没有反应或者卡死。所以,一定要从 Win32 模式开始,再创建 x64 模式,并把 Win32 的设置复制到 x64 模式中,便可以解决这个问题。

    接着,我们开始新建 x64 模式,因为我们要开发的是 64 位程序。我们选中项目工程,以此选择 “属性” —> “配置属性” —> “配置管理器” —> “活动解决方案平台”选择“新建”。这时,就会来到“新建解决方案平台”页面。我们选择“x64”,并从 Win32 中复制设置,创建新的项目平台,点击“确定”。这时,就可以使用 x64 模式编译 64 位程序了。

    然后,我们继续对 .asm 文件进行设置,将其包含到项目工程中来编译链接。选中“myasm.asm”文件,右击选择“属性”,来到“myasm.asm”属性页进行设置。在 命令行 中输入“ml64 /c %(fileName).asm”,在 输出 中输入“%(fileName).obj”,其它保持默认即可,点击“确定”即可完成设置。

    经过上述几个步骤,我们成功为 x64 程序添加 .asm 文件并设置包含到项目工程中编译链接。接下来,我们就开始讲解如何在 .asm 文件中写汇编代码了。
    实现原理对于 64 位程序在 .asm 中写代码,需要遵循以下几个规则:

    会变文件 .asm 文件必须以关键字 .CODE 开始,关键字 END 结束,大小写都可以。
    .code ; 此处写汇编指令代码end

    所有的汇编代码以函数方式组织在一起。也就是说,我们要将汇编代码封装成一个个汇编函数。要注意 64 位汇编中的函数声明以及调用约定:
    .code; _MyAdd是汇编函数_MyAdd proc ; 此处写汇编函数的代码_MyAdd endpend
    其中, _MyAsm 是汇编函数的名称,proc 是汇编函数的关键字,endp 是汇编函数的结尾关键字。
    要注意和 32 位汇编函数的区别:32 位汇编函数调用约定 __stdcall,所有参数从右到左依次入栈,通过压栈传递参数。64 位汇编函数的调用约定 __fastcall,前 4 个参数是从左至右依次存放于RCX、RDX、R8、R9寄存器里面,剩下的参数从左至右顺序入栈。
    编码实现myasm.asm.code_MyAdd proc xor rax, rax mov rax, rcx add rax, rdx add rax, r8 add rax, r9 ret_MyAdd endpend
    ASM_64_Test.cppextern "C" ULONGLONG _MyAdd(ULONGLONG a1, ULONGLONG a2, ULONGLONG a3, ULONGLONG a4);int _tmain(int argc, _TCHAR* argv[]){ ULONGLONG a1 = 1; ULONGLONG a2 = 2; ULONGLONG a3 = 3; ULONGLONG a4 = 4; ULONGLONG b = _MyAdd(a1, a2, a3, a4); printf("b=%d\n", b); system("pause"); return 0;}
    程序测试我们直接运行程序,成功显示正确的计算结果:

    然后,我们查看 RAX、RCX、RDX、R8、R9 这 5 个寄存器里的值,和上述我们讲解的相一致:

    总结要特别注意一点就是,如果你使用 VS2013 开发环境,或者你使用其它的开发环境也遇到这样一个问题就是:在 x64 模式下,添加 .asm 文件,并设置在 .asm 属性页 中设置“自定义生成工具”后,界面出现卡死、无反应现象。可以尝试下面的解决方法:

    首先,不要在 x64 模式下面进行设置 .asm 属性页。更换到 x86 模式,即 Win32 模式下,然后再在 .asm 属性页 中设置“自定义生成工具”,这时可以正常设置。
    然后,在在 .asm 属性页 中设置“自定义生成工具”,这时,我们再“新建” x64 的解决方案平台,从 Win32 中复制设置。

    那么,这时,我们就可以在 x64 下正常对“自定义生成工具”进行设置了。
    同时,也要要注意和 32 位汇编函数的区别:32 位汇编函数调用约定 __stdcall,所有参数从右到左依次入栈,通过压栈传递参数。64 位汇编函数的调用约定 __fastcall,前 4 个参数是从左至右依次存放于RCX、RDX、R8、R9寄存器里面,剩下的参数从左至右顺序入栈。
    参考参考自《Windows黑客编程技术详解》一书
    1  留言 2018-11-07 11:44:24
  • 内联汇编之32位程序

    背景内联汇编是指在 C/C++ 代码中嵌入的汇编代码,与全部是汇编的汇编源文件不同,它们被嵌入到 C/C++ 的大环境中。内联汇编方式两个作用,一是程序的某些关键代码直接用汇编语言编写,可提高代码的执行效率;二是有些操作无法通过高级语言实现,或者实现起来很困难,必须借助汇编语言达到目的。
    32 位程序和 64 位程序下使用内联汇编的方式,有很大的差别。现在,我们对此分别进行介绍。本篇文章主要介绍的是在 32 位程序中使用内联汇编。
    实现过程使用内联汇编要用到 __asm 关键字,它可以出现在任何允许 C/C++ 语句出现的地方。对 __asm 关键字的使用有两种方式:

    __asm 块,要添加大括号
    __asm { // 汇编代码 }
    __asm 语句,在每条汇编指令之前加 __asm 关键字
    __asm // 汇编代码

    显然,第一种方法与 C/C++ 的风格很一致,并且把汇编代码和 C/C++ 代码清楚地分开,还避免了重复输入 __asm 关键字,因此推荐使用第一种方法。
    不像在 C/C++ 中的“{ }”,__asm 块的“{ }”不会影响 C/C++ 变量的作用范围。同时,__asm 块可以嵌套,而且嵌套也不会影响变量的作用范围。
    为了与低版本的 Visual C++ 兼容,_asm 和 __asm 具有相同的意义。另外,Visual C++ 支持标准 C++ 的 asm 关键字,但是它不会生成任何指令,它的作用仅限于使编译器不会出现编译错误。要使用内联汇编,必须使用 __asm 而不是 asm 关键字。
    编码实现void MyFunc(char *pszText){ printf("%s\n", pszText);}int _tmain(int argc, _TCHAR* argv[]){ char str1[] = "__asm{ }"; char str2[] = "__asm"; // 32位程序内联汇编 第一种方式 __asm { lea eax, str1 push eax mov eax, MyFunc call eax } // 32位程序内联汇编 第二种方式 __asm lea eax, str2 __asm push eax __asm mov eax, MyFunc __asm call eax system("pause"); return 0;}
    程序测试我们直接运行程序,程序成功显示两行字符串,说明两种方式的内联汇编均使用成功。

    总结在 32 位程序中使用内联汇编比较方便,就两种形式,一种是有大括号的:
    __asm{ // 汇编代码}
    另一种是没有大括号的:
    __asm // 汇编代码
    这两种方式是等价的,大家可以根据自己的程序需要,自行选择使用哪种方式即可。
    参考参考自《Windows黑客编程技术详解》一书
    1  留言 2018-11-07 11:40:52

发送私信

我想要你幸福,但我希望我是你幸福的原因

17
文章数
13
评论数
eject