My Asm example


Let program a simple working assembly code called from the Visual Studio Cpp project. The assembly code is intentional placed in the external file.

Create a simple C++ console project. Right click on the project name in the solution explorer, choose the Build dependencies and then the Build customization submenu and check the masm box:

Now we are ready to add a new item. Give it a name: myAsmFile.asm – Now right click on the asm file and choose the properties. You have to see the Microsoft Macro Assembler to the left of property pages. If not, you will not be able to build this example. Please check out this window:

The content of the asm file:

.386
.MODEL	FLAT, C
.STACK	128
.CONST
.DATA
.CODE	;Indicates the start of a code segment.
mySeg1 SEGMENT PAGE PUBLIC 'MUJ'
		power2 PROC NEAR
			push	ebp				; Save EBP
			mov		ebp, esp		; Move ESP into EBP so we can refer to arguments on the stack
			mov		eax, [ebp + 8]	; Get first argument
			mov		ecx, [ebp + 12]	; Get second argument
			dec		ecx
			shl		eax, cl			; EAX = EAX * ( 2 ^ CL )
			pop		ebp				; Restore EBP
			ret						; Return with sum in EAX
		power2 ENDP
	mySeg1 ENDS
END


Then insert this code to the main.cpp

#include "stdafx.h"

extern "C" int power2(int num, int power);

int main()
{
	int prs = power2(2, 2);
	std::cout << "prs 2^2: " << prs << std::endl;

	prs = power2(2, 3);
	std::cout << "prs 2^3: " << prs << std::endl;

	prs = power2(2, 4);
	std::cout << "prs 2^4: " << prs << std::endl;

	return 0;
}

We run the program and see the results:

 prs 2^2: 4
 prs 2^3: 8
 prs 2^4: 16

Now let disassemble the results. Here follow the disassembly for the first case 2 ^ 2:

00301680  /$ 55             push ebp
00301681  |. 8BEC           mov ebp,esp
00301683  |. 83EC 18        sub esp,18
00301686  |. 53             push ebx
00301687  |. 56             push esi
00301688  |. 6A 02          push 2
0030168A  |. 6A 02          push 2
0030168C  |. E8 6F390000    call myAsm4.00305000

The second case 2 ^ 3:

003016C4  |. 6A 03          push 3
003016C6  |. 6A 02          push 2
003016C8  |. E8 33390000    call myAsm4.00305000

And the thirth case 2 ^ 4:

003016FF  |. 6A 04          push 4
00301701  |. 6A 02          push 2
00301703  |. E8 F8380000    call myAsm4.00305000

The core procedure looks like this:

00305000   55               push ebp
00305001   8BEC             mov ebp,esp
00305003   8B45 08          mov eax,dword ptr ss:[ebp+8]
00305006   8B4D 0C          mov ecx,dword ptr ss:[ebp+C]
00305009   49               dec ecx
0030500A   D3E0             shl eax,cl
0030500C   5D               pop ebp
0030500D   C3               retn

The 3 cases differ from each other only with the pushed values. The parameters a 4 bytes long and must be taken from the stack to calculate the result. The register EAX in line 00305003 is the base value, and the ECX is the power value. Decrementing of ECX is a must, otherwise the results are twice so big.

The return address is the 1st value pushed on stack, the EBP is the 2st value, the EAX gets 3th and the ECX the 4th value pushed on stack. The result of calculation is as always in the EAX register.

Here is the working code:

,

Leave a Reply

Your email address will not be published.