Tuesday, July 27, 2010

Adding Numbers Example

This Tutorial is intended to respond a question about how to get what a function returns, and where to stored the return value of the function.

EAX The "Official" place for the return value of a function


As you may read in http://www.freebsd.org/doc/en/books/developers-handbook/x86-return-values.html

This function should return the number 5

int getNumber5(void){
__asm
{
mov eax,5
}
}

This is simple. We only copy 5 to eax register. And because eax is the "official" return register its the same as:



int getNumber5(void){
return (5);
}

Remember that in C/C++, and every language that I know, you may only return one value, or an address pointer. Usually 32 bits(4 bytes) in a 32 bit architecture, this is because of the size of EAX.


EAX is Not a Stack!


Please remember that EAX, is part of the general purpose registers.
Refer to http://rodrigosavage.blogspot.com/2010/07/hello-world-with-inline-asm.html#purposeReg


or to Intel documentation 253665.pdf, where they explain each register an how should you use it.

What intel says about each register:

  • EAX — Accumulator for operands and results data
  • EBX — Pointer to data in the DS segment
  • ECX — Counter for string and loop operations
  • EDX — I/O pointer
  • ESI — Pointer to data in the segment pointed to by the DS register; source pointer for string operations
  • EDI — Pointer to data (or destination) in the segment pointed to by the ES register; destination pointer for string operations
  • ESP — Stack pointer (in the SS segment)
  • EBP — Pointer to data on the stack (in the SS segment)
This means that EAX, is an Accumulator(http://en.wikipedia.org/wiki/Accumulator_(computing)).
And ESP, will point to the top of the stack that is manage by Intel push and pops instructions.

The next image was taken from Intel documantation.
It shows how are the registers and there names.














ADD — Add Instruction


Intel 253666.pdf documentation states that:
Adds the destination operand (first operand) and the source operand (second
operand) and then stores the result in the destination operand. The destination
operand can be a register or a memory location; the source operand can be an imme-
diate, a register, or a memory location. (However, two memory operands cannot be
used in one instruction.) When an immediate value is used as an operand, it is sign-
extended to the length of the destination operand format.


This means that the code
add EAX, number

will be the same as C/C++ like
EAX = EAX + number;

Just keep in mind that this is an integer addition.

Intel inline assembly function for adding two numbers


int addNumbers(int n1,int n2){
__asm
{
mov eax,n1
add eax,n2
}
}

This function only receives two parameters, that are identified by n1 and n2. We first copy n1 to EAX register
and later we add eax + n2, and save the result to eax(the return accumulator).

this would be the same as C/C++ like:
int addNumbers(int n1,int n2){
EAX=n1;
EAX = EAX+n2;
}
(keep in mind that you cannot not access eax directly or any other CPU register like this, inline assembly is necessary to do so).
Or at higher level:
int addNumbers(int n1,int n2){
return(n1+n2);
}


Final Code


#include <stdio.h>
#include <iostream>
using namespace std;

int addNumbers(int n1,int n2){
__asm
{
mov eax,n1
add eax,n2
}// In C/C++, what the function returns is usally stored in eax register

//return n1+n2;
}

void execQuestion2()
{

char format[] = "%u \n";
int n1 = 10;
int n2 = 11;
int result = addNumbers(n1, n2);

cout << n1 << " + " << n2 << " = ";

__asm {
// push n1 and n2 onto the stack
mov eax, n1
push eax
mov eax, n2
push eax
// call "addNumbers" method
call addNumbers
push eax // we put the result of addNumbers into the stack
// Question 2.4 - put formatting onto the stack
lea eax, format
push eax
// Question 2.5 - call "printf" method
call DWORD ptr printf
// Question 2.6 - empty the stack
pop ebx
pop ebx
pop ebx
pop ebx

}
}

int main()
{
execQuestion2() ;
getchar();
}


If you have any problem or question
pleas don't hesitate in commenting :)

I will gladly respond. No matter the question ^^

4 comments:

Anonymous said...

Hi there!

I just want to do a shout out to all the TUKS COS222 students who's currently leaching of this blog!

Savage you might not be aware of it but we have a practical assignment for a module at University that reffered us here (which was very cheap of them!).

This is why your live traffic feed has numerous entries from South Africa at the moment.

The question that provoked this tutorial was most likely a student busy with this practical assignment, because your tutorial uses the exact code the lecturer supplied us and you have just completed the practical for everyone!

However, I want to point out a few things:

The addNumbers function is written in C++ and looks like this:

int addNumbers(int num1, int num2)
{
return(num1 + num2)
}

Your code still works however, as "call addNumbers" will still take the top two entries in the eax stack.

I hope this will teach the Computer Science Department to stop being cheap and leach from others! So much for plagiarism!

Anonymous said...

Whoever just posted the last message dam get a life.. Its not like the prac's are a freaken exam were meant to LEARN about new concepts and how all this asm jazz fits together. And so be it if the guy just posted a tutorial for us atleast we'll have a nice start to the semester prac's.

Savage said...

Hi students from TUKS COS222, I will publish the solution to this tutorial until August second.

Have fun coding it! :)

Mata ne ^^

Savage said...

Hello Anonymous who wrote on July 29!

Thank you very much for the head up :). I will try to make this blog the best!.
I need your participation and your help.

I noticed that you said:
However, I want to point out a few things:

The addNumbers function is written in C++ and looks like this:

int addNumbers(int num1, int num2)
{
return(num1 + num2)
}

Your code still works however, as "call addNumbers" will still take the top two entries in the eax stack.

And how i stated above, and explained that eax is an accumulator!, and not a stack. Also remember that the only way that you may use the stack is by using push and pop. You cannot change directly the ESP register(pointer to the top of the stack), unless you are in real mode(you may check this also in the Intel documentation 253665.pdf, or wait until you see real and protected mode in you Operating System course).

So this mean that my old code was correct.
Please comment if you think otherwise.
Thanks! :)
PD.: Please always leave your email, or your name.
Just use the Anonymous account if you are to shy to comment