I'm new in assembly coding. I need a shift operation in Visual C project. & wrote the below listing.
I want to shift two number at the same time.
to break the loop, one number must be zero.
Is there an effective way?

/********************************/
void pairshift(int *num1,int *num2)
{

__asm{

mov ecx, num1
mov edx, num2
mov eax,
mov ebx,

start: sar eax,1
sar ebx,1
cmp eax,0
jz end
cmp ebx,0
jz end
jmp start
end: mov ,eax
mov ,ebx
}
}
/********************************/
Posted on 2003-05-20 07:27:30 by alidemirkaya
`````` IF eax AND ebx == 0 break the loop
start:
sar eax,1
sar ebx,1
or  eax, ebx
jnz start
mov [ecx],eax
mov [edx],eax

IF eax AND ebx == 0
or IF eax=0 AND ebx <>0
or IF eax<>0 AND ebx==0
break the loop

start:
sar eax,1
sar ebx,1
test  eax, ebx
jnz start
mov [ecx],eax
mov [edx],ebx``````
Regards,
Lingo
Posted on 2003-05-20 16:41:10 by lingo12
Do you realise that the loop will never terminate if both numbers are negative?

SAR copies the top most (signed bit) down with the shift, I think you mean SHR, which does not.

First here's an optimisation of your own code:

``````
start:
shr eax,1
shr ebx,1 ;  This will set the ZERO flag, no need for a cmp
jz end
cmp ebx,0
jnz start ; Invert the jump condition, and jump back instead of forwards
``````

There is however a non-looping way to do this:

Look at BSR, it scans for the top most set-bit. This will allow you to remove the loop.
The code will probably be longer, but will execute faster due to the removal of the loop.

Mirno
Posted on 2003-05-20 16:47:56 by Mirno
Since you're using the C compiler, you might as well do it in C to make it portable.

while( num1 && num2 ){ num1 >> 1; num2 >> 1; }
Posted on 2003-05-20 18:23:09 by iblis
Thanks for all. I tried c++ code(my original code is in c++). c++ coded version is two time faster then the asm coded.
But in the future i want to convert all the code into asm.

But I wonder if it is possibble to shift two number at the same time. ie. shift command must effect two registers at the same time.
Posted on 2003-05-21 05:58:07 by alidemirkaya
i wonder if the produces the same result:

``````
mov	eax, a
mov	ebx, b

@@go:
mov	edx, eax

@@findmaxbit:
push	eax
push	ebx

or	eax, ebx
xor	eax, ebx
push	eax
and	edx, ebx
pop	edx
or	eax, edx
bsr	ecx, edx

pop	ebx
pop	eax

@@reduce:
shr	ebx, ecx
shr	eax, ecx

jmp	@@somewhere
; now one is zero but i don't
; know which!
``````

finds the min max bit of the numbers (i hope!), reduces both by that much, then is done.

----------
edit:
erm, no this does not do what i intended.
Posted on 2003-05-21 06:00:50 by abc123
alidemirkaya,
"c++ coded version is two time faster then the asm coded."
Amazing!!!
Could you please post the assembly code produced by this fantastic C/C++ compiler?

But in the future i want to convert all the code into asm.
I'm wondering why?

Regards,
Lingo
Posted on 2003-05-22 20:38:43 by lingo12
I'm sory. Inline coded version is two time faster then asm coded. Because of removed function calling
Thanks.
``````
/*******************************************************/
//Visual 6.0 is used.
//

#include <stdio.h>
#include <time.h>

/*inline */void pairshift1(int *num1,int *num2)
{
while((*num1)&&(*num2))
{
(*num1)>>=1;
(*num2)>>=1;
}
}
void pairshift2(int *num1,int *num2)
{

__asm{

mov		ecx, num1
mov		edx, num2
mov		eax, [ecx]
mov		ebx, [edx]

start:	sar eax,1
sar ebx,1
cmp     eax,0
jz      end
cmp     ebx,0
jz      end
jmp start
end:    mov [ecx],eax
mov [edx],ebx
}
}

int main()
{
int i;
time_t t1,t2;
time(&t1);
for(i=0;i<100000000;i++)
{
num1=5;
num2=3;
pairshift1(&num1,&num2);
}
time(&t2);
printf("Loop 1:%d secs\n",t2-t1);
time(&t1);
for(i=0;i<100000000;i++)
{
num1=5;
num2=3;
pairshift2(&num1,&num2);
}
time(&t2);
printf("Loop 2:%d secs\n",t2-t1);
return 0;
}
/*******************************************************/
Loop 1:7 secs
Loop 2:6 secs
Press any key to continue

/*******************************************************/``````
Posted on 2003-05-23 00:31:16 by alidemirkaya
``````void pairshift2(int *num1,int *num2)
{

__asm{

mov	eax, num1
mov	edx, num2

start:	sar	DWORD PTR [eax], 1
jz	end
sar	DWORD PTR [edx], 1
jnz	start
jmp	end2
end:
sar	DWORD PTR [edx], 1
end2:

}
}``````
Posted on 2003-05-23 01:02:49 by bitRAKE
perhaps:

``````
mov	eax, num1
mov	ebx, num2
cmp	eax, ebx
cmovg	eax, ebx
bsr	edx, eax
shr	eax, edx
shr	ebx, edx
``````

im also interested to know how mirno would do it using "bsr" and no loops
Posted on 2003-05-23 04:02:09 by abc123
Maybe:
``````
pairshift:
bsr eax,[esp+4]
bsr ecx,[esp+8]
cmp ecx,eax
comvg ecx,eax
sar dword ptr[esp+4],cl
sar dword ptr[esp+8],cl
ret 8
``````

Not too sure
Posted on 2003-05-23 08:07:52 by roticv
What does that "comvg" instruction do? ;)
Posted on 2003-05-25 15:48:07 by gliptic
conditional move

move if greater than ...
Posted on 2003-05-25 20:06:29 by abc123
The above BSR examples are pretty much what I'd thought of, but there is one difference....

The result of the C while loop will be one or two zeroed values, while a single BSR, shift will result in a value of 1.

You can't increment ecx afterwards, because in the case of MSB being set, the result is 31 + 1 = 32, and SHR only shifts using the bits 0..4.
So you need a second round of SHR instructions, with a shift of 1.

I would have commented all this sooner, but a roof leaking incedent forced me off line, followed by a short holiday!

It looks like some people didn't notice the SAR thing I first mentioned though, bitRAKE's loop will not end if both numbers are "negative".

One other thing to realise here is the cost of the call. In C, the calling time of this code will be a fair percentage of the total runtime. On top of that if the call is changed to being inline, the use of assembly will disable the optimiser, not only will it disable it, it will push the current state on the stack (the compiler cannot tell which registers are in use by an __asm section), to ensure things are as it left it.

It's my feeling that the level of complexity here, the compiler will always win (just because it can tell what happens before, and after the call, and optimise around it).

Mirno
Posted on 2003-05-27 11:34:04 by Mirno