Jump to content

What's wrong with this code?

- - - - -

  • Please log in to reply
3 replies to this topic

#1
jdanowitz

jdanowitz

    Newbie

  • Members
  • Pip
  • 2 posts
Hi--
I tried to write a simple assembler code in LINUX (Intel) that does the ceil of log2. It just equates the BSF and BSR. If they are equal, then returns one of them, if they are not equal, returns 1 more then BSR. I get for 512 a result of 10 even through I know that BSR and BSF are both equal to 9 here. Where am I going wrong? (i.e. Jlog2(512) returns 10 and not 9 !!) Code below.

Thanks,
Jeff


inline int Jlog2(register int a) 

{

	   int b;

	   asm (

			 "BSR  %%eax,%0; \n"

			 "BSF  %%ebx,%0; \n"

			 "CMP  %%eax,%%ebx; \n"

			 "JE   EXT; \n"

			 "INC  %%eax; \n"

			 "EXT:"

			 :"=r"(b)        /* output */

			 :"a"(a)         /* input */

		   );       	  

	   return b;

}


Edited by TkTech, 15 July 2010 - 11:32 AM.
Added code tags.


#2
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
Ok...I know this is AT&T syntax, which should have the operands reversed. However, you have them "backwards," in Intel order. Try swapping the EAX/%0 and EBX/%0. In Intel syntax, you'd have:

bsr     eax, %0
bsf     ebx, %0
cmp     eax, ebx
je      .ext
inc     eax
.ext:
Note that the operands for the first two instructions are in the same as yours. I'm not very versed in AT&T syntax because it's a complete mess to me, but I believe this is how you'd do it in GAS (i.e. your way):
bsrl    %0, %%eax
bsfl    %0, %%ebx
cmpl    %%eax, %%ebx
je      EXT
incl    %%eax
EXT:
Lemme know if it works or blows up in your face.
sudo rm -rf /

#3
jdanowitz

jdanowitz

    Newbie

  • Members
  • Pip
  • 2 posts
Hi,

I replaced it all with:

inline int Jlog2(register int a)
{
int b;
asm (
"BSR %0,%%eax; \n"
"BSF %0,%%edx; \n"
"CMP %%edx,%%eax; \n"
"JE EXT; \n"
"INC %%eax; \n"
"EXT:"
:"=r"(b)
:"a"(a)
);
return b;
}

It doesn't make a difference whether i use edx, ebx or ecx. Same stuff.
The problem is that apparently the CMP is not working. It doesn't see when they are equal. It apparently returns not equal all the time. I never use the JE.
Now, if I put "CMP %%edx,%%edx; \n" --- it always sees equal (obviously) and never does the increase.
So somehow the comparison is not correct.

Any ideas? (btw it's not blowing up!!)

btw2: I wrote this for windows like
__forceinline int log2(register int num )
{
__asm
{
BSR EAX,num
BSF EBX,num
CMP EAX,EBX
JE EXT
INC EAX
EXT:
}
// Return with result in EAX

}

This works great in windows (intel). I just cannot port this to LINUX.

Jeff

#4
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
That'd be because it's using AT&T syntax, possibly the most annoying thing ever devised since LISP. :) Did you make sure to use the l at the ends of everything there? Should be CMPL, INCL, etc. You always have to do that with AT&T syntax:
Intel   mov     eax, ebx
AT&T    movl    %ebx, %eax

Intel   mov     ax, es:[ebp + 8*ecx + 80h]
AT&T    movw    %es:$0x80(%ebp,%ecx,8), %ax

You have to put b/w/l/q on the ends of the operands, otherwise it'll pick a default, which may or may not be the size you want.
sudo rm -rf /




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users