▶ 书中第十三章的程序,主要讲了汇编语言和 C/++ 相互调用的方法
● 代码,汇编中调用 C++ 函数
1 ; subr.asm 2 INCLUDE Irvine32.inc 3 4 askForInteger PROTO C 5 showInt PROTO C, value:SDWORD, outWidth:DWORD 6 7 OUTPUT_WIDTH = 8 8 MAX_POWER = 10 9 10 .data 11 intVal DWORD ? 12 13 .code 14 SetTextOutColor PROC C, color:DWORD 15 mov eax, color 16 call SetTextColor 17 call Clrscr 18 ret 19 SetTextOutColor ENDP 20 21 DisplayTable PROC C 22 INVOKE askForInteger ; 调用 C++ 函数输入整数 23 mov intVal, eax ; 保存返回值 24 mov ecx, MAX_POWER 25 26 L1: 27 push ecx 28 shl intVal, 1 ; 每次乘以 2 29 INVOKE showInt, intVal, OUTPUT_WIDTH ; 调用 C++ 函数显示结果 30 call Crlf 31 pop ecx 32 loop L1 33 34 ret 35 DisplayTable ENDP 36 37 END
1 // main.cpp 2 #include <iostream> 3 #include <iomanip> 4 using namespace std; 5 6 extern "C" // 声明外部 asm 过程和 C++ 函数 7 { 8 void SetTextOutColor(unsigned color); // 设置终端字体和背景颜色 9 void DisplayTable(); // 显示表格 10 11 int askForInteger(); // 输入整数 12 void showInt(int value, int width); // 按宽度 width 显示数字 value 13 } 14 15 int main() 16 { 17 SetTextOutColor(0x1E); // 蓝底黄字 18 DisplayTable(); 19 20 getchar(); 21 getchar(); 22 return 0; 23 } 24 25 int askForInteger() 26 { 27 int n; 28 cout << "Target integer [1, 90000]: "; 29 cin >> n; 30 return n; 31 } 32 33 void showInt(int value, int width) 34 { 35 cout << setw(width) << value; 36 }
■ 输出结果
● 代码,汇编调用 C/C++ 库函数和自定义函数。有个奇怪的 bug,scanf 至少要在主函数中用一次,否则汇编的目标文件找不到,暂时不明。
1 ; asmMain.asm 2 INCLUDE Irvine32.inc 3 4 printSingle PROTO C, aSingle:REAL4, precision:DWORD ; 声明外部函数(库函数不用声明) 5 6 TAB = 9 7 8 .code 9 asmMain PROC C ; 程序入口 10 11 .data ; 测试 printf 12 format BYTE "%.2f",TAB,"%.3f",0dh,0ah,0 13 val1 REAL8 456.789 14 val2 REAL8 864.231 15 .code 16 INVOKE printf, ADDR format, val1, val2 ; 调用 printf 17 ; 书本注释曰,不能用 INVOKE ptrintf 来显示 REAL4 型变量? 18 19 .data ; 测试 scanf 20 strSingle BYTE "%f",0 21 strDouble BYTE "%lf",0 22 float1 REAL4 1234.567 23 double1 REAL8 1234567.890123 24 25 .code 26 INVOKE scanf, ADDR strSingle, ADDR float1 ; 调用 scanf,覆盖掉原本的值 27 INVOKE scanf, ADDR strDouble, ADDR double1 28 29 .data ; 测试栈传参 printf 和自定义函数 30 valStr BYTE "float1 in ASM = %.3f", 0dh, 0ah, 0 31 32 .code 33 fld float1 ; 将 float1 转存到 FPU 栈中 34 sub esp,8 ; 指到栈的高位 35 fstp qword ptr [esp] ; 当成 double 取出 36 push OFFSET valStr ; 栈传参来调用 printf 37 call printf 38 add esp,12 39 INVOKE printSingle, float1, 3 ; 自定义外部函数来显示 float1 40 41 call Crlf 42 ret 43 asmMain ENDP 44 45 END
1 // main.cpp 2 #define _CRT_SECURE_NO_WARNINGS // 关闭 MVC++ 关于 scanf 被 scanf_s 取代的警告 3 4 #include <stdio.h> 5 #include <string> 6 #include <strstream> 7 8 using namespace std; 9 10 extern "C" 11 { 12 void asmMain(); 13 void printSingle(float d, int precision); 14 } 15 16 void printSingle(float d, int precision) 17 { 18 strstream temp; 19 temp << "float1 in C++ = %." << precision << "f" << '