News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

[Help] - Digit Sum

Started by yq8, May 05, 2015, 03:38:23 AM

Previous topic - Next topic

yq8

Hey Guys,

Today I am trying to calculate the digitsum of a number.

e.g.:

1234   -> 10
82749 -> 30


Often people have recommend me to first code myself in another easier language, then its easier to code it in asm.
So I did with C++ :


int DigitSum(int a)
{
int b = 0;
while (a > 0) {
b += a % 10;
a /= 10;
}
return b;
}


Pretty compact function.
Now I try to code this in inline asm in C++.
I am unsure how to realize this, this is my attempt and thats I thought I would do it:


int AsmDigSum(int a)
{
__asm
{
mov eax, a // Move inputnumber to eax
xor ecx, ecx // Set ecx to 0
jpl : // jumpmark
blabla      // somehow perform modulo of eax?
add edx, eax // add result of module operation into edx
idiv edx, 10 // div result by 10
mov eax, edx  // mov result of all calculation back to eax?
dec eax // decrease eax to prevent infinite loop?
jne jpl // if eax is > 0 jump to label
}
}


Obviously this code is not compileable.
Can someone tell me:

1) If my general idea of doing it (look at asm pseudocode) is correct?
2) How can I do this: b += a % 10 ?
3) Is my condition for the while loop correct? Also the decreasing operation?
4) Am I using the correct indices?

Would be cool if someone who is more experienced can give me some hints :)

jj2007

You were pretty close, but you should urgently have a look at \Masm32\Help\opcodes.chm

mov eax, 1234567895 ; Move inputnumber to eax
push ebx ; non-volatile register must be preserved
xor ebx, ebx ; Set sum ebx to 0
mov ecx, 10 ; Set ecx to 10
jpl: ; jumpmark
cdq
idiv ecx ; div eax by 10; result in eax, remainder in edx
add ebx, edx    ; add remainder to sum
test eax, eax
jne jpl         ; if eax is > 0 jump to label
xchg eax, ebx ; shortest way to move result to eax
pop ebx         ; get old ebx back

yq8

Hey,
Nice, I think I now understood it!
And yes, I will read a bit more into the .chm file now before asking my question ;)
Thanks for the advice and help !

Gunther

Hi yq8,

just another hint: If you have a working C or C++ source for your problem, compile the source with the switch -S on the command line. The result is the compiler's assembly language code which could give you the right direction to go. And welcome to the forum.

Gunther
You have to know the facts before you can distort them.

yq8

@Gunther : Check your PM :)

Gunther

Quote from: yq8 on May 06, 2015, 01:55:35 AM
@Gunther : Check your PM :)

Done. Check your PM, too.

Gunther
You have to know the facts before you can distort them.

Gunther

Here is a simple example for using with the GCC. First the main procedure:

#include <stdio.h>
#include <stdlib.h>

extern int Add(int x, int y);

int main()
{
    int a = 3;
    int b = 4;
    int c = 0;
    c = Add(a, b);
    printf("c = %d\n",c);
    return 0;
}

Here the C code for the function Add in a seperate file:

int Add(int x, int y)
{
    return x+y;
}

Compiling the function Add with the following comand line switch:

gcc -O3 -S -masm=intel add.c

leads to following assembly language output:

.file "add.c"
.intel_syntax noprefix
.text
.p2align 4,,15
.globl _Add
.def _Add; .scl 2; .type 32; .endef
_Add:
mov eax, DWORD PTR [esp+8]
add eax, DWORD PTR [esp+4]
ret
.ident "GCC: (rev, Built by MinGW-builds project) 4.8.0 20130314 (experimental)"

The O switch determines the level of optimization. Without O switch ===> nothing optimized
O1 ===> level 1
O2 ===> level 2
O3 ===> level 3 (highest optimization level).

You should be able to do it similar with VS. I hope that gives the idea.

Gunther
You have to know the facts before you can distort them.

yq8

Hey,

I now tried to make the Parameter "a" customizable like in a function.
But something is wrong and I don't know what.
This is what I've coded :


push ebp
mov ebp, esp
mov eax,[ebp+0x0c]
xor ebx, ebx
push ebx
mov ecx, 10
jx:
cdq
idiv ecx
add ebx, edx
test eax, eax
jne jx
xchg eax, ebx
pop ebx
ret 0x0c         


What did I do wrong? ;o

Gunther

Hi yq8,

please show us your function call (number and type of passed parameters). Your last instruction is:

    ret    12

It could be that this is wrong.

Gunther
You have to know the facts before you can distort them.

yq8

My parameter is just the integer value  123.
It can't be the return which is wrong.
I tried :

ret 0xC
ret 0x8
ret 0x4
ret

None of them seems to be the right one.

dedndave

what he means is, show us the PROC and ENDP, perhaps the PROTO
also, show us where you pass arguments and call it

dedndave

you PUSH EBP, then PUSH EBX....

at the end, you POP EBX, but never POP EBP or LEAVE

when RET executes, it tries to return to an address that was the saved EBP contents - oops   :redface:

dedndave

it's probably simpler to let the assembler handle the stack frame

;###############################################################################################

        INCLUDE    \Masm32\Include\Masm32rt.inc

;###############################################################################################

MyFunction PROTO :DWORD,:DWORD

;###############################################################################################

    ;    .DATA

;***********************************************************************************************

     ;   .DATA?

;###############################################################################################

        .CODE

;***********************************************************************************************

main    PROC

        INVOKE  MyFunction,eax,5

        print   chr$(13,10)
        inkey
        INVOKE  ExitProcess,0

main    ENDP

;***********************************************************************************************

MyFunction PROC USES EBX arg1:DWORD,arg2:DWORD

    mov     ebx,arg1
    mov     eax,arg2
    print   ustr$(eax),13,10,13,10
    ret

MyFunction ENDP

;###############################################################################################

        END     main


on the PROC line, "USES EBX" will cause the assembler to preserve and restore the contents of EBX
the assembler will take care of the stack frame and balance the stack at exit

yq8

Hey dedndave,
Thanks for your reply.
Since I call my asm function from C# I can't do the stack handling
automatically.

I tried to pop ebp too, as you've suggested, but that seems not to work either.

push ebp
mov ebp, esp
mov eax,[ebp+0x0c]
xor ebx, ebx
push ebx
mov ecx, 10
jx:
cdq
idiv ecx
add ebx, edx
test eax, eax
jne jx
xchg eax, ebx
pop ebx
pop ebp
ret 0x0c

dedndave

how many arguments are you passing to this function ?