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:

原文地址:https://www.cnblogs.com/dreamafar/p/6006076.html