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
}
}
/********************************/
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
}
}
/********************************/
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
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:
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
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
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; }
while( num1 && num2 ){ num1 >> 1; num2 >> 1; }
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.
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.
i wonder if the produces the same result:
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.
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.
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
"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
I'm sory. Inline coded version is two time faster then asm coded. Because of removed function calling
Thanks.
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
/*******************************************************/
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:
}
}
perhaps:
im also interested to know how mirno would do it using "bsr" and no loops
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
Maybe:
Not too sure
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
What does that "comvg" instruction do? ;)
conditional move
move if greater than ...
move if greater than ...
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
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