汇编语言调用C语言/C++实例:乘法表
现在编写一个简单的应用程序,提示用户输入整数,通过移位的方式将其与 2 的幕 (2¹〜2ⁿ) 相乘,并用填充前导空格的形式再次显示每个乘积。输入-输出使用 C++。汇编模块将调用 3 个 C++ 编写的函数。程序将由 C++ 模块启动。
DisplayTable 在调用 C++ 函数时不一定要用 INVOKE。PUSH 和 CALL 指令也能得到同样的结果。对 showInt 的调用如下所示:
在 Project 菜单中选择 Properties,在窗口左边的 Configuration Properties 条目下,选择 Linker。在右边面板的 Additional Library Directories 条目中输入 c:\Irvine。
示例如下图所示。点击OK关闭 Project Property Pages 窗口。现在 Visual Studio 就可以找到 Irvine32 链接库了。
汇编语言模块
汇编模块包含一个函数 DisplayTable。它调用 C++ 函数 askForInteger 从用户输入一个整数。它还使用循环结构把整数 intVal 重复左移,并调用 showInt 进行显示。; C++ 调用ASM函数. INCLUDE Irvine32.inc ;外部C++函数 askForInteger PROTO C showInt PROTO C, value:SDWORD, outWidth:DWORD OUT_WIDTH = 8 ENDING_POWER = 10 .data intVal DWORD ? .code ;--------------------------------------------- SetTextOutColor PROC C, color:DWORD ; ; 设置文本颜色,并清除控制台窗口 ; 调用 Irvine32 库函数 ;--------------------------------------------- mov eax,color call SetTextColor call Clrscr ret SetTextOutColor ENDP ;--------------------------------------------- DisplayTable PROC C ; ; 输入一个整数 n 并显示范围为 n * 2^1 ~ n * 2^10的乘法表 ;---------------------------------------------- INVOKE askForInteger ; 调用 C++ 函数 mov intVal,eax ; 保存整数 mov ecx,ENDING_POWER ; 循环计数器 L1: push ecx ; 保存循环计数器 shl intVal,1 ; 乘以 2 INVOKE showInt,intVal,OUT_WIDTH call Crlf pop ecx ; 恢复循环计数器 loop L1 ret DisplayTable ENDP END在 DisplayTable 过程中,必须在调用 showInt 和 newLine 之前将 ECX 入栈,并在调用后将 ECX 出栈,这是因为 Visual C++ 函数不会保存和恢复通用寄存器。函数 askForInteger 用 EAX 寄存器返回结果。
DisplayTable 在调用 C++ 函数时不一定要用 INVOKE。PUSH 和 CALL 指令也能得到同样的结果。对 showInt 的调用如下所示:
push OUT_WIDTH ;最后一个参数首先入栈
push intVal
call showInt ;调用函数
add esp,8 ;清除堆栈
C++ 测试程序
下面查看启动程序的 C++ 模块。其入口为 main(),保证执行所需 C++ 语言的初始化代码。它包含了外部汇编过程和三个输岀函数的原型:// main.cpp // 演示C++程序和外部汇编模块的函数调用 #include <iostream> #include <iomanip> using namespace std; extern "C" { // 外部 ASM 过程: void DisplayTable(); void SetTextOutColor( unsigned color ); // 局部 C++ 函数: int askForInteger(); void showInt( int value, int width ); } // 程序入口 int main() { SetTextOutColor( 0x1E ); // 蓝底黄字 DisplayTable(); // 调用 ASM 过程 return 0; } // 提示用户输入一个整数 int askForInteger() { int n; cout << "Enter an integer between 1 and 90,000: "; cin >> n; return n; } // 按特定宽度显示一个有符号整数 void showInt( int value, int width ) { cout << setw(width) << value; }
生成项目
将 C++ 和汇编模块添加到 Visual Studio 项目,并在 Project 菜单中选择 Build Solution。程序输出
当用户输入为 90 000 时,乘法表程序产生的输出如下:Visual Studio 项目属性
如果使用 Visual Studio 生成集成了 C++ 和汇编代码的程序,并且调用 Irvine32 链接库,就需要修改某些项目设置。以 Multiplication_Table 程序为例。在 Project 菜单中选择 Properties,在窗口左边的 Configuration Properties 条目下,选择 Linker。在右边面板的 Additional Library Directories 条目中输入 c:\Irvine。
示例如下图所示。点击OK关闭 Project Property Pages 窗口。现在 Visual Studio 就可以找到 Irvine32 链接库了。