Intel x86 assembly assignment problem... **FIXED**

oLLie

Diamond Member
Jan 15, 2001
5,203
1
0
If this is bad or wrong, I'll edit my post and take it out (posted in off topic too). I'm not asking someone to do it for me, it's pretty much done just the result string is writing incorrectly. The purpose is to take two char strings and add them digit by digit (assuming the numbers you want to add are too large for registers).
THANKS IN ADVANCE GUYS
The problem is something with me constructing the result string; it always prints out some junk or some kind of happy face thing. I ran it in debug and eax always has the correct sum of the digits, so I set a watch flag for 'result' and it goes: "IIIII7" => "IIII7" => "III6" => "II5" => "I4" => "|". Reversed this is almost the correct sum: 99999 + 45678 = 145677. I'm missing the 1 out front and the string is shortening or something. I tried writing the null terminator at the beginning of add2BigNums but it didn't help, I tried using a separate register for the result string too but that didn't help either. CODE BELOW:

#include<iostream.h>
#include<stdio.h>
#define BUF 1024



char * yourName = "Oliver Le";
char * userID = "68474298";


//this integer will keep track of the carry throughout the program
int carry;


//
//Given the integers a and b, this function adds a, b, and the carry together.
//If the sum is greater than 9, we subtract 10 from the sum, and put 1 in the carry.
//If the sum is less than or equal to 9, we put 0 in the carry.
//
int add2Digits( int a, int b )
{
int return_val;

__asm
{

push eax //retain the previous state of the machine
push ebx

xor eax, eax //clear the registers we are using
xor ebx, ebx

mov eax, a //copy the first int to a register
mov ebx, b //copy the second int to a register

add eax, ebx //add the two digits
xor ebx, ebx //clear ebx to hold the carry
mov ebx, carry //copy the carry to ebx

add eax, ebx //add the carry to the result
mov carry, 0 //clear the carry again
cmp eax, 10 //see if we need another carry
jl done
sub eax, 10 //normalize the result to be 0-9
mov carry, 1 //set a new carry

done:
mov return_val, eax //copy the result from eax to return_val
pop ebx //return the previous state
pop eax
}

return return_val; // return_val gets put into eax by the compiler


}


//
//Given two character strings that represent numbers, this funciton adds the two
//numbers together and puts the result in "char* result".
//
void add2BigNums( char* num1, char* num2, int len, char* result )
{

__asm
{
push ebx
push ecx //preserve the original state
push edx
push edi //edi will hold garbage
push esi //esi will be a pointer-value

xor ebx, ebx
xor ecx, ecx //clear out our registers
xor edx, edx
xor edi, edi
xor esi, esi

mov carry, 0 //clear the carry on the first-run
mov esi, len //initialize our pointer-value
mov ebx, result
mov byte ptr[ebx+esi+1], 0
dec esi //it will look at the last digits of each number first

begin_loop:
mov ecx, num1 //have ecx point to num1 char array
mov dl, [ecx+esi] //copy the esi-th digit of num1 into edx
sub dl, 48 //convert to an int
push edx //prepare it for add2Digits

mov ecx, num2 //have ecx point to num2 char array
mov dl, [ecx+esi] //copy the esi-th digit of num2 into edx
sub dl, 48 //convert to an int
push edx //prepare it for add2Digits

call add2Digits //add the two digits

pop edi //throw the second int away into edi
pop edi //throw the first int away into edi

//mov ecx, result //have ecx point to the result char array
add eax, 48 //convert the int back into a character
mov [ebx+esi+1], eax //insert the result into the last
//position of the result array
dec esi //get the next two digits
cmp esi, 0 //if esi becomes less than zero we're done adding
jl done_adding
jmp begin_loop //otherwise continue the loop

done_adding:
//mov esi, len //change esi back to len
//mov byte ptr[ecx+esi+1], 0 //insert the null terminator
xor edx, edx //clear edx to hold the last carry
mov edx, carry //copy the carry into edx
mov [ebx], edx //copy the carry into the first place

pop esi //return the machine to the original state
pop edi
pop edx
pop ecx
pop ebx
}
}




void main()
{


char result[BUF];


cout << "ICS 51 lab1 (Spring 2002)" << endl
<< yourName << endl
<< userID << endl << endl;

int temp = add2Digits( 9, 9 );
cout << "9 + 9 = " << carry << temp << endl;

carry = 0;
temp = add2Digits( 0, 0 );
cout << "0 + 0 = " << carry << temp << endl;

carry = 1;
temp = add2Digits( 8, 1 );
cout << "8 + 1 + 1 = " << carry << temp << endl;

carry = 1;
temp = add2Digits( 3, 2 );
cout << "3 + 2 + 1 = " << carry << temp << endl;


add2BigNums( "99999", "45678", 5, result );
cout << "99999 + 45678 = " << result << endl;

add2BigNums( "5467815132154687984",
"0000010000032165498", 19, result );
cout << "5467815132154687984 + 0000010000032165498 = " << result << endl;

add2BigNums( "99999999999999999",
"00000000000000001", 17, result );
cout << "99999999999999999 + 00000000000000001 = " << result << endl;

add2BigNums( "2", "9", 1, result );
cout << "2 + 9 = " << result << endl;

add2BigNums( "0", "0", 1, result );
cout << "0 + 0 = " << result << endl;

}

/*SAMPLE OUTPUT

ICS 51 lab1 (Spring 2002)
Put Your Name Here!!
Put Your StudentID Here!!

9 + 9 = 18
0 + 0 = 00
8 + 1 + 1 = 10
3 + 2 + 1 = 06
99999 + 45678 = 145677
5467815132154687984 + 0000010000032165498 = 5467825132186853482
99999999999999999 + 00000000000000001 = 100000000000000000
2 + 9 = 11
0 + 0 = 0
Press any key to continue

*/
 

singh

Golden Member
Jul 5, 2001
1,449
0
0
First, a suggestion: Having a separate "adding" function is overkill. In fact, the code would be much more clear, short and concise without the separate add function.

Second, an error in your program. Perhaps this is the cause of your troubles:

Suppose I want to add two "numbers" with DIFFERENT number of digits. For example, "2000" + "1". Now, your program loop only keeps track of 1 position which is fine when both the "numbers" have the same amount of digits. But it won't work when the two number strings have different amount of digits.

This code won't work:
mov ecx, num1 //have ecx point to num1 char array
mov dl, [ecx+esi] //copy the esi-th digit of num1 into edx
sub dl, 48 //convert to an int
push edx //prepare it for add2Digits

mov ecx, num2 //have ecx point to num2 char array
mov dl, [ecx+esi] //copy the esi-th digit of num2 into edx
sub dl, 48 //convert to an int
push edx //prepare it for add2Digits

Your "index" variable is in "ecx+esi". But that will only work when both numbers being added have the same count of digits.
 

oLLie

Diamond Member
Jan 15, 2001
5,203
1
0
They're making us have 2 functions and they specifically told us the length for both nums will be the same. Thanks for looking at it for me though.
 

singh

Golden Member
Jul 5, 2001
1,449
0
0
OK, but please provide the full specifications next time :)

Your problem is in two places. First:
//mov ecx, result //have ecx point to the result char array
add eax, 48 //convert the int back into a character
mov [ebx+esi+1], eax //insert the result into the last

Notice that you need to store a byte (char) value, but you are storing "eax" which is obviously not what you want:) You need to change the last line to this:
mov [ebx+esi+1], al


Second:
xor edx, edx //clear edx to hold the last carry
mov edx, carry //copy the carry into edx
mov [ebx], edx //copy the carry into the first place


You are just directly copying the carry without turning it into ASCII. The result is that you will effectively null-terminate the string or write a "happy" character on the screen. You need to remove the last line, and add these two:
add edx, 48
mov [ebx], dl


And that will take care of your problems :) At least I hope so.
 

oLLie

Diamond Member
Jan 15, 2001
5,203
1
0
LOL IT'S FIXED! After taking singh's advice, the last change I had to make was mov [ecx], edx to mov [ecx], dl because of course the final carry char is only 1 byte!

JOY!