▶ 书中第十三章的程序,主要讲了汇编语言和 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. 让Delphi XE5跟其他版本的Delphi共存 [转]

    找到Delphi XE5的安装根目录  ....  \Program Files (x86)\Embarcadero\RAD Studio\12.0\bin下的cglm.ini文件, 打开cglm.i ...

  2. JavaScrip之BOM、DOM

    BOM 浏览器对象模型(BrowserObjectModel),可以对浏览器窗口进行访问和操作.使用 BOM,开发者可以移动窗口.改变状态栏中的文本以及执行其他与页面内容不直接相关的动作. 使 Jav ...

  3. https 不检验证书

    System.Net.ServicePointManager.ServerCertificateValidationCallback += (s, cert, chain, sslPolicyErro ...

  4. [蓝桥杯]ALGO-81.算法训练_动态数组使用

    从键盘读入n个整数,使用动态数组存储所读入的整数,并计算它们的和与平均值分别输出.要求尽可能使用函数实现程序代码.平均值为小数的只保留其整数部分. 样例输入: 样例输出: 样例输入: 样例输出: 题目 ...

  5. 【spring boot】映射properties文件属性--到Java对象

    描述 将*.properties中的内容映射到java对象中: 主要步骤 添加 @Component 注解: 使用 @PropertySource 注解指定配置文件位置: 使用 @Configurat ...

  6. zTree分批异步加载方式下实现节点搜索功能(转载)

    原文地址:https://segmentfault.com/a/1190000004657854 最近公司做一个项目用到zTree,zTree功能强大就不用多说了,相信用过的人都知道.       公 ...

  7. Zabbix 课程大纲

    Zabbix 课程笔记  day1 Zabbix 安装  day1 Zabbix 添加主机 day1 Zabbix 创建监控项目 day1 Zabbix 创建触发器 day1 Zabbix 告警内容配 ...

  8. centos6.8下l2tp客户端xl2tpd的安装配置

    环境: DigitalOcean centos6.8作为l2tp客户端 ros6.43.8作为l2tp服务端 1.安装xl2tp和ppp rpm -ivh http://mirrors.yun-idc ...

  9. [UE4]宏

    宏和函数的区别 “展开”就是直接将宏代码直接复制粘贴替换到所有使用当前宏的地方.这个跟C++中的宏是一样的. 1.宏可以有多个入口,多个出口,函数只有一个入口,一个出口 2.宏的参数可以使用“Exec ...

  10. [UE4 ]Is Locally Controlled的局限性

    一.在有机器人的游戏中,就不能使用IsLocallyControlled判断.而是要使用这个方法: 二.因为机器人也是属于本地控制的角色.所以不能使用IsLocallyControlled判断是否是本 ...