News:

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

Main Menu

[Help] - Length of Integer

Started by yq8, May 04, 2015, 01:00:53 AM

Previous topic - Next topic

yq8

Hello community,

This is my first post on this board, and I just started for fun learning a bit more about asm. :)
I am coding my asm code by using C++ inline asm capability.
What I am trying to achieve is finding out how many digits a number (integer) has.
For example:

Quote1739 would be 4
9823823 would be 7

etc.


// Count digits of int with asm
int AsmCountDigit(int a)
{
__asm
{
              mov eax, a            // Store int a in eax
              // how to count the length of value in eax..?
}
}


Can someone give me some advices :)
So far I've come up with this, but the return value is always 0?


// Count digits of int with asm
int AsmCountDigit(int a)
{
__asm
{
cdq
xor eax, edx
sub eax, edx
xor ebx, 10
jp1:
add ecx, 1
xor edx, edx
idiv ebx
test eax, eax
jne jp1
}
}


~yq8


EDIT : Sorry, wrong subforum, please move the topic to the beginner section.

rrr314159

Hi yq8, welcome,

change "xor ebx, 10" to "mov ebx, 10"
I am NaN ;)

yq8

Hey,
First of all, thanks for your reply.
I tried it as you recommended, tho, the return value is always 0..


// Count digits of int with asm
int AsmCountDigit(int a)
{
__asm
{
cdq
xor eax, edx
sub eax, edx
mov ebx, 10
jp1:
add ecx, 1
xor edx, edx
idiv ebx
test eax, eax
jne jp1
}
}

jj2007

Welcome to the forum :icon14:
mov eax, 1234657890
mov ebx, 10
xor ecx, ecx    ; set digit counter to zero
jpl: cdq
idiv ebx
inc ecx
test eax, eax
jne jpl
print str$(ecx), " digits"


Quote from: yq8 on May 04, 2015, 01:00:53 AMI just started for fun learning a bit more about asm. :)

Just for fun, hm. What's the name of your teacher?

dedndave

;    L = Trunc( B * Log(2) ) + 1
;    where L is the string length in bytes and B is the integer length in bits
;    if the value is negative, add 1 byte for the minus sign


Log(2) ~ 0.30102999566
i'll let you work out how to do it   :P

L is the maximum length
so, it may be 1 digit less

rrr314159

yq8,

Jj's right, set ecx to zero; in masm it always starts there. But that can't explain why you always get 0 answer (ecx would have to always magically equal the negative of your digit count). So you're doing something wrong when you read that value. How are you returning the value to your C routine? Probably you have to put ecx in eax: "mov eax, ecx" at the end of your routine .. ?
I am NaN ;)

yq8

Quote from: jj2007 on May 04, 2015, 03:14:18 AM
Welcome to the forum :icon14:
mov eax, 1234657890
mov ebx, 10
xor ecx, ecx    ; set digit counter to zero
jpl: cdq
idiv ebx
inc ecx
test eax, eax
jne jpl
print str$(ecx), " digits"


Quote from: yq8 on May 04, 2015, 01:00:53 AMI just started for fun learning a bit more about asm. :)

Just for fun, hm. What's the name of your teacher?

Hey,
Your way cause an exception for me, - integer overflow. (But the input number is definitly in the integer range, its '1234') :icon_confused:

And I am serious, I don't have to learn masm for school or university.
I just got my interests on it after I've seen some people using inline asm in C++
So, this is not some kind of homework, if you suspect this ;)

jj2007

Quote from: yq8 on May 04, 2015, 06:50:33 AM
Your way cause an exception for me, - integer overflow. (But the input number is definitly in the integer range, its '1234') :icon_confused:

You must have a very special CPU then.
Or you don't master the art of copy & paste 8)
Or you forgot to return the counter in eax ("mov eax, ecx" as posted by rrr above).

Re homework, it is certainly sheer coincidence that just a few hours ago somebody who calls himself "Madara-Uchiha" posted exactly the same question in a different forum, right?

yq8

Quote from: jj2007 on May 04, 2015, 07:27:48 AM
Quote from: yq8 on May 04, 2015, 06:50:33 AM
Your way cause an exception for me, - integer overflow. (But the input number is definitly in the integer range, its '1234') :icon_confused:

You must have a very special CPU then.
Or you don't master the art of copy & paste 8)
Or you forgot to return the counter in eax ("mov eax, ecx" as posted by rrr above).

Re homework, it is certainly sheer coincidence that just a few hours ago somebody who calls himself "Madara-Uchiha" posted exactly the same question in a different forum, right?

Hey,
Madara-Uchiha is a friend I asked about this problem. He said he wasn't sure either and will ask somewhere else, I am not sure in which forum he asked, tho.
Haven't heared anything from him till now.

Well my CPU is not special I guess, and I can master c&p :D
I'm just a beginner, so probably some more explanation is needed ;)
Can you comment every line so I know whats going on?

// Count digits of int with asm
int  AsmDigCount(int a)
{
__asm
{
mov eax, a         
mov ebx, 10         
xor ecx, ecx
jpl: cdq
idiv ebx
inc ecx
test eax, eax
jne jpl
}
}


And about the int overflow :



This is the dissassembly of VS (input number for a was 5000):


jj2007

Quote from: yq8 on May 04, 2015, 07:52:43 AMCan you comment every line so I know whats going on?
OK

// Count digits of int with asm
int  AsmDigCount(int a)
{
   __asm
   {
      mov eax, a         
      mov ebx, 10   ; divide by 10
      xor ecx, ecx  ; digit counter
      jpl: cdq      ; set edx to zero or, if eax < 0, to -1
      idiv ebx      ; divide signed
      inc ecx       ; increase digit counter
      test eax, eax ; see if we are finished
      jne jpl
      mov eax, ecx
   }
}


There will be no integer overflow in this code. But you need to add mov eax, ecx at the end to pass the result back to C/C++. After the jne jpl, eax is zero - so you currently return zero digits to C/C++, and I have no idea what is being done with this value afterwards.

The best way to solve this is to zip your executable and attach it under your next reply.

Siekmanski

Hi yq8,

Welcome to the forum.

Marinus
Creative coders use backward thinking techniques as a strategy.

yq8

Quote from: jj2007 on May 04, 2015, 08:53:21 AM
Quote from: yq8 on May 04, 2015, 07:52:43 AMCan you comment every line so I know whats going on?
OK

// Count digits of int with asm
int  AsmDigCount(int a)
{
   __asm
   {
      mov eax, a         
      mov ebx, 10   ; divide by 10
      xor ecx, ecx  ; digit counter
      jpl: cdq      ; set edx to zero or, if eax < 0, to -1
      idiv ebx      ; divide signed
      inc ecx       ; increase digit counter
      test eax, eax ; see if we are finished
      jne jpl
      mov eax, ecx
   }
}


There will be no integer overflow in this code. But you need to add mov eax, ecx at the end to pass the result back to C/C++. After the jne jpl, eax is zero - so you currently return zero digits to C/C++, and I have no idea what is being done with this value afterwards.

The best way to solve this is to zip your executable and attach it under your next reply.
Hi,
Thanks for your explanation, tho as a beginner I have problems understanding your comments?
This is how I understand the code:


// Count digits of int with asm
int  AsmDigCount(int a)
{
__asm
{
mov eax, a // Move inputnumber to eax
mov ebx, 10 // Move 10 to ebx
xor ecx, ecx // Not sure, probably setting ecx to 0?
jpl : cdq // double operand size, - what is the operand here?
idiv ebx // divide ?? by value of ebx?
inc ecx // increment value of ecx
test eax, eax // check if eax == eax? (isnt that always true)
jne jpl // jump to jpl if ??? is not 0
mov eax, ecx // mov value of ecx to eax
}
}


This code works now btw.
But I am hear to learn something and not just to copy code, so I like to understand
every line here now.

E.g.

Quotemov ebx, 10   ; divide by 10
Why? Doesn't this just mov 10 to ebx?

Quotexor ecx, ecx  ; digit counter
Uhm, okay, this xor checks if one of those conditions is true, right?
And how gets ecx modified here? Is it set to 0?

jpl: cdq ; set edx to zero or, if eax < 0, to -1
Uhm. I really dont understand that. jppl  is the jump target and cdq doubles the size of an operand, so says google.
Mind explaining it again? :)


Would be cool if you can tell me why my commentary is wrong :)
Also here is a working exe now :


dedndave

CDQ - convert dword to qword
CWD - convert word to dword
CBW - convert byte to word

to extend the length of a signed integer....
if the initial integer is positive (high bit = 0), then all the additional bits are 0's
if the initial integer is negative (high bit = 1), than all the additional bits are 1's

for example, CBW....
00000001 -> 00000000_00000001 (the value +1 is extended)
11111111 -> 11111111_11111111 (the value -1 is extended)

jj2007

Quote from: yq8 on May 04, 2015, 10:19:31 AMThanks for your explanation, tho as a beginner I have problems understanding your comments?
My comments have been a bit too concise, sorry

> This code works now btw.
After changing what exactly?

Quotemov ebx, 10   ; divide by 10
> Why? Doesn't this just mov 10 to ebx?
Indeed. I meant "see below, this is your divisor"

Quotexor ecx, ecx  ; digit counter
Efficient way of setting ecx to zero. Check what xor does in number theory.

jpl: cdq
This is a label and an instruction in the same line. Split it:
jpl:
    cdq

if eax<0, cdq sets edx to -1
if eax>=0, cdq sets edx to 0
See Dave's explanation below, and check \Masm32\Help\opcodes.chm

QuoteAlso here is a working exe now :

The one that throws the exception would be more interesting, actually. We should understand what caused the bug...

dedndave

the exception seems to be thrown by IDIV when (EDX:EAX / DivisorOperand) overflows a dword register
from what i can see, he did not set EDX prior to IDIV