首页 > 代码库 > Multiplication Table Example
Multiplication Table Example
Let’s write a simple application that prompts the user for an integer, multiplies it by ascending
powers of 2 (from 21 to 210) using bit shifting, and redisplays each product with leading padded
spaces. We will use C++ for the input-output. The assembly language module will contain calls
to three functions written in C++. The program will be launched from C++.
Assembly Language Module
The assembly language module contains one function, named DisplayTable. It calls a C++
function named askForInteger that inputs an integer from the user. It uses a loop to repeatedly
shift an integer named intVal to the left and display it by calling showInt.
; ASM function called from C++ INCLUDE Irvine32.inc ; External C++ functions: askForInteger PROTO C showInt PROTO C, value:SDWORD, outWidth:DWORD ;newLine PROTO C OUT_WIDTH = 8 ENDING_POWER = 10 .data intVal DWORD ? .code ;--------------------------------------------- SetTextOutColor PROC C, color:DWORD ; ; Sets the text colors and clears the console ; window. Calls Irvine32 library functions. ;--------------------------------------------- mov eax,color call SetTextColor call Clrscr ret SetTextOutColor ENDP ;--------------------------------------------- DisplayTable PROC C ; ; Inputs an integer n and displays a ; multiplication table ranging from n * 2^1 ; to n * 2^10. ;---------------------------------------------- INVOKE askForInteger ; call C++ function mov intVal,eax ; save the integer mov ecx,ENDING_POWER ; loop counter L1: push ecx ; save loop counter shl intVal,1 ; multiply by 2 INVOKE showInt,intVal,OUT_WIDTH ;INVOKE newLine ; output CR/LF pop ecx ; restore loop counter loop L1 ret DisplayTable ENDP END
In DisplayTable, ECX must be pushed and popped before calling showInt and newLine because
Visual C++ functions do not save and restore general-purpose registers. The askForInteger
function returns its result in the EAX register.
DisplayTable is not required to use INVOKE when calling the C++ functions. The same
result could be achieved using PUSH and CALL instructions. This is how the call to showInt
would look:
push OUT_WIDTH ; push last argument first push intVal call showInt ; call the function add esp,8 ; clean up stack
You must follow the C language calling convention, in which arguments are pushed on the
stack in reverse order and the caller is responsible for removing arguments from the stack after
the call.
C++ Startup Program
Let’s look at the C++ module that starts the program. Its entry point is main( ), ensuring the execution
of required C++ language initialization code. It contains function prototypes for the external
assembly language procedure and the three exported functions:
// main.cpp // Demonstrates function calls between a C++ program // and an external assembly language module. #include <iostream> #include <iomanip> using namespace std; extern "C" { // external ASM procedures: void DisplayTable(); void SetTextOutColor(unsigned color); // local C++ functions: int askForInteger(); void showInt(int value, int width); } // program entry point int main() { SetTextOutColor( 0x1E ); // yellow on blue DisplayTable(); // call ASM procedure return 0; } // Prompt the user for an integer. int askForInteger() { int n; cout << "Enter an integer between 1 and 90,000:"; cin >> n; return n; } // Display a signed integer with a specified width. void showInt( int value, int width ) { cout << setw(width) << value; }
Building the Project Our Web site (www.asmirvine.com) has a tutorial for building combined
C++/Assembly Language projects in Visual Studio.
Program Output Here is sample output generated by the Multiplication Table program when
the user enters 90,000:
Multiplication Table Example