▶ 书中第十三章的程序,主要讲了汇编语言和 C/++ 相互调用的方法

● 代码,汇编中调用 C++ 函数

 ; subr.asm
INCLUDE Irvine32.inc askForInteger PROTO C
showInt PROTO C, value:SDWORD, outWidth:DWORD OUTPUT_WIDTH =
MAX_POWER = .data
intVal DWORD ? .code
SetTextOutColor PROC C, color:DWORD
mov eax, color
call SetTextColor
call Clrscr
ret
SetTextOutColor ENDP DisplayTable PROC C
INVOKE askForInteger ; 调用 C++ 函数输入整数
mov intVal, eax ; 保存返回值
mov ecx, MAX_POWER L1:
push ecx
shl intVal, ; 每次乘以 2
INVOKE showInt, intVal, OUTPUT_WIDTH ; 调用 C++ 函数显示结果
call Crlf
pop ecx
loop L1 ret
DisplayTable ENDP END
 // main.cpp
#include <iostream>
#include <iomanip>
using namespace std; extern "C" // 声明外部 asm 过程和 C++ 函数
{
void SetTextOutColor(unsigned color); // 设置终端字体和背景颜色
void DisplayTable(); // 显示表格 int askForInteger(); // 输入整数
void showInt(int value, int width); // 按宽度 width 显示数字 value
} int main()
{
SetTextOutColor(0x1E); // 蓝底黄字
DisplayTable(); getchar();
getchar();
return ;
} int askForInteger()
{
int n;
cout << "Target integer [1, 90000]: ";
cin >> n;
return n;
} void showInt(int value, int width)
{
cout << setw(width) << value;
}

■ 输出结果

● 代码,汇编调用 C/C++ 库函数和自定义函数。有个奇怪的 bug,scanf 至少要在主函数中用一次,否则汇编的目标文件找不到,暂时不明。

 ; asmMain.asm
INCLUDE Irvine32.inc printSingle PROTO C, aSingle:REAL4, precision:DWORD ; 声明外部函数(库函数不用声明) TAB = .code
asmMain PROC C ; 程序入口 .data ; 测试 printf
format BYTE "%.2f",TAB,"%.3f",0dh,0ah,
val1 REAL8 .
val2 REAL8 .
.code
INVOKE printf, ADDR format, val1, val2 ; 调用 printf
; 书本注释曰,不能用 INVOKE ptrintf 来显示 REAL4 型变量? .data ; 测试 scanf
strSingle BYTE "%f",
strDouble BYTE "%lf",
float1 REAL4 .
double1 REAL8 . .code
INVOKE scanf, ADDR strSingle, ADDR float1 ; 调用 scanf,覆盖掉原本的值
INVOKE scanf, ADDR strDouble, ADDR double1 .data ; 测试栈传参 printf 和自定义函数
valStr BYTE "float1 in ASM = %.3f", 0dh, 0ah, .code
fld float1 ; 将 float1 转存到 FPU 栈中
sub esp, ; 指到栈的高位
fstp qword ptr [esp] ; 当成 double 取出
push OFFSET valStr ; 栈传参来调用 printf
call printf
add esp,
INVOKE printSingle, float1, ; 自定义外部函数来显示 float1 call Crlf
ret
asmMain ENDP END
 // main.cpp
#define _CRT_SECURE_NO_WARNINGS // 关闭 MVC++ 关于 scanf 被 scanf_s 取代的警告 #include <stdio.h>
#include <string>
#include <strstream> using namespace std; extern "C"
{
void asmMain();
void printSingle(float d, int precision);
} void printSingle(float d, int precision)
{
strstream temp;
temp << "float1 in C++ = %." << precision << "f" << '\0';
printf(temp.str(), d);
} int main()
{
asmMain();
scanf(""); // 如果没有这一句就会报错:LNK2019,无法解析的外部符号 _scanf,该符号在函数 _asmMain 中被引用
getchar();
getchar();
return ;
}

■ 程序输出

456.79  864.231
123.456
123456789.123456789

float1 in ASM = 123.456
float1 in C++ = 123.456

● 代码,汇编调用 C 库函数,system 和 file 相关。还是有那个要在主函数里用一次 printf 和 scanf 的问题。

 ; asmMain.asm
.
.MODEL flat, C system PROTO, pCommand:PTR BYTE ; 声明一堆库函数
printf PROTO, pString:PTR BYTE, args:VARARG
scanf PROTO, pFormat:PTR BYTE,pBuffer:PTR BYTE, args:VARARG
fopen PROTO, mode:PTR BYTE, filename:PTR BYTE
fclose PROTO, pFile:DWORD BUFFER_SIZE =
.data
str1 BYTE "cls",
str2 BYTE "dir/w",
str3 BYTE "Enter the name of a file: ",
str4 BYTE "%s",
str5 BYTE "Failed to open the file", 0dh, 0ah,
str6 BYTE "Succeeded to open the file", 0dh, 0ah,
modeStr BYTE "r", fileName BYTE DUP()
pBuf DWORD ?
pFile DWORD ? .code
asm_main PROC
INVOKE system,ADDR str1 ; cls
INVOKE system,ADDR str2 ; dir INVOKE printf,ADDR str3 ; 提示信息
INVOKE scanf, ADDR str4, ADDR fileName ; 输入文件名 INVOKE fopen, ADDR fileName, ADDR modeStr ; 尝试打开文件
mov pFile, eax .IF eax ==
INVOKE printf,ADDR str5
jmp quit
.ELSE
INVOKE printf,ADDR str6
.ENDIF
INVOKE fclose, pFile quit:
ret
asm_main ENDP
END
 // main.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h> extern "C" void asm_main(); void main()
{
asm_main();
scanf("");
printf("");
getchar();
getchar();
}

《汇编语言 基于x86处理器》第十三章高级语言接口部分的代码 part 2的更多相关文章

  1. 《汇编语言 基于x86处理器》第九章字符串与数组部分的代码

    ▶ 书中第九章的程序,主要讲了字符串相关的输入.输出,以及冒泡排序.二分搜索 ● 代码,Irvine32 中的字符串库函数代码范例 INCLUDE Irvine32.inc .data str1 BY ...

  2. 《汇编语言 基于x86处理器》第八章高级过程部分的代码 - 两种规范计算数组元素的和

    ▶ 输入 Count 个 32 位有符号整数,计算他们的和 ● 代码,使用堆栈传参 ;// Sum_main.asm,主过程 INCLUDE Irvine32.inc EXTERN PromptFor ...

  3. 《汇编语言 基于x86处理器》第十一章 MS-DOS 编程部分的代码 part 2

    ▶ 书中第十一章的程序,主要讲了 Windows 接口,在小黑框中进行程序交互 ● 在屏幕指定位置输出带自定义属性的文字 INCLUDE Irvine32.inc .data outHandle HA ...

  4. 《汇编语言 基于x86处理器》第十二章浮点数部分的代码

    ▶ 书中第十二章的程序,主要讲了 FPU 的指令和浮点数计算的过程 ● 代码,简单的 32 为浮点数测试 INCLUDE Irvine32.inc INCLUDE macros.inc .data f ...

  5. 《汇编语言 基于x86处理器》第七章整数运算部分的代码

    ▶ 书中第七章的程序,使用各种位移运算,加深了对内存.寄存器中整数类型变量存储的认识 ● 代码,双字数组右移 4 位 INCLUDE Irvine32.inc COUNT = ; 右移位数 .data ...

  6. 《汇编语言 基于x86处理器》第六章条件处理部分的代码

    ▶ 书中第六章的程序,使用了条件判断和跳转来实现一些功能 ● 代码,查找数组首个非零值 INCLUDE Irvine32.inc .data intArray SWORD , , , , , , , ...

  7. 《汇编语言 基于x86处理器》前五章的小程序

    ▶ 书中前五章的几个小程序,基本的运算操作,使用了作者的库 Irvine32 和 Irvine64(一开始以为作者网站过期了,各网站上找到的文件大小都不一样,最后发现是要搭梯子 Orz,顺利下载).注 ...

  8. 《汇编语言 基于x86处理器》第十章 - 运行一个 16位实地址汇编程序

    ▶ 书上第 10 章,主要讲了宏,引用了一个 16 位实地址的程序,从代码开始到运行 ● 代码 ; main.asm INCLUDE Macros.inc IF IsDefined( RealMode ...

  9. 《汇编语言 基于x86处理器》第十章结构和宏部分的代码

    ▶ 书中第十章的程序,主要讲了结构与宏的使用 ● 代码,使用结构,对比是否对齐的性能差距 INCLUDE Irvine32.inc INCLUDE macros.inc structN STRUCT ...

随机推荐

  1. 利用VMware虚拟机安装CentOS7

    CentOS7镜像下载:http://isoredirect.centos.org/centos/7/isos/x86_64/CentOS-7-x86_64-DVD-1804.iso VMware虚拟 ...

  2. 使用apache设置绑定多个域名或网站

    来源:百度知道  http://jingyan.baidu.com/article/363872ecec3e496e4ba16fdc.html 配置完成后可能是能访问了,但是跳转的路径总是不对,这时候 ...

  3. Tablacus Explorer双心封装版

    Tablacus Explorer双心封装版 http://cloud.189.cn/t/mYj67j7r2Afq (TablacusExplorer17.3.27双心封装版.exe) http:// ...

  4. vue之v-bind

    接触Vue已经有很长一段时间了,后来因为工作的原因,已经有差不多一年的时间没有碰过它了,害怕时间久,自己就完全忘记了,所以还是想抽出一点时间将以前的知识整理一下. 刚接触vue的时候,觉着最神奇的地方 ...

  5. MySQL总论

    1. MySQL基本概念 1.1.  数据库的概念 数据库,简而言之就是存储数据的仓库,可以按照一定的数据结构存储管理大量的数据及数据与数据之间的关系,它本质上是一种信息管理系统.数据库根据存储采用的 ...

  6. 学习-工作:GTD

    ylbtech-学习-工作:GTD GTD就是Getting Things Done的缩写,翻译过来就是“把事情做完”,是一个管理时间的方法.GTD的核心理念概括就是必须记录下来要做的事,然后整理安排 ...

  7. centos7 安装pip+python3.6

    centos7安装pip 1.执行:yum install python-pip 若没有python-pip包,先执行:yum -y install epel-release,再执行yum insta ...

  8. 00013 - top命令详解

    top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器. top显示系统当前的进程和其他状况,是一个动态显示过程,即可以通过用户按键来不 ...

  9. Git配置SSH Key

    最近看到很多人在配置Git时,遇到很问题,网上教程千篇一律.这儿自己单独记录一份. Git配置SSH Key 1.检查本机是否有ssh key设置,切换到.ssh目录 $ cd ~/.ssh 或cd ...

  10. c#线程间传递参数

    线程操作主要用到Thread类,他是定义在System.Threading.dll下.使用时需要添加这一个引用.该类提供给我们四个重载的构造函数(以下引自msdn).        Thread (P ...