tags:

views:

58

answers:

4

I have discovered a bug in some assembly code I have been working with but can't figure how to fix it. When shifting left by 0 the result ends up being 0 instead of jut the number. The same applies when shifting to the right. Any and all help is much appreciated.

function sal(n,k:integer):integer;
begin
 asm
 cld
 mov    cx,     k
@1:
  sal n, 1
  loop @1
 end;
 sal:= n;
end;

function sar(n,k:integer):integer;
begin
 asm
  cld
  mov   cx,     k
@1:
  sar   n,      1
  loop  @1
 end;
 sar:=n;
end;

I have tried to changed them in the following way and it still does not work properly.

function sal(n,k:integer):integer;
begin
 asm
 cld
 mov    cx,     k
 jcxz @done
@1:
  sal n, 1
  loop @1
@done:
 end;
 sal:= n;
end;

function sar(n,k:integer):integer;
begin
 asm
  cld
  mov   cx,     k
 jcxz @done
@1:
  sar   n,      1
  loop  @1
@done:
 end;
 sar:=n;
end;
A: 

what about shr and shl? http://www.delphibasics.co.uk/RTL.asp?Name=Shr http://www.delphibasics.co.uk/RTL.asp?Name=Shl

Andrey
The program uses shr and shl in addition sar and sal
Roy McAvoy
A: 

about your error: if k is zero then loop will decrease it and get negative value. loop checks only for zero. you number gets decreased until it gets zero again eventually. this shifts your number so much that all bits are shifted out.

Andrey
Yes i figured out that is what the problem is but I know very little about assembly and am not quite sure how to fix it.
Roy McAvoy
A: 

The probmem is that the mov instruction doesn't set any of the flags. You probably want to add a test instruction before the conditional jump.

Also, I assume there's a reason you're doing this in a loop instead of a with a single instruction? It is possible to stick the count in CL.

torak
I really have no experience with assembly I was just assigned to try and fix this bug. I thought maybe if I checked for 0 first and exited before the loop it would work but that is not the case.
Roy McAvoy
Just had a look in the intel manual, and the jcxz should do what you want actually.
torak
This is in a 16 bit execution environment right?
torak
this piece of assembly code is inside a function of a pascal program
Roy McAvoy
Since Pascal seems to be available for both 16 and 32 bit platforms, that doesn't really nail it down. The reason it might matter is that if you're in a 32 bit environment, then the byte codes for jcxz would be interpreted as jecxz. jecxz tests the whole of ECX, and you only initialised the lower 16 bits (CX). If you change it try to initialise ECX with the value of k instead of just CX it should produce an error if you are compiling for a 16-bit environment. If you're in a 32-bit environment it should work, and hopefully fix your problem. You should then also change jcxz to jecxz.
torak
when i compile the program with the jecxz i get a syntax error on jecxz, but it works fine with jcxz
Roy McAvoy
A: 

You have a typo... Use clc instead cld, cld instruction will clear direction flag and clc will clear carry flag.

Right asm code...

asm
      mov    cx, k         //ecx for 32bit cpu mode
@1:
      clc 
      sal    n, 1
      loop   @1
end;

or

asm
      mov    cx, k         //ecx for 32bit cpu mode
@1: 
      shl    n, 1
      loop   @1
end;

or

asm
      mov    cl, k        
      shl    n, cl
end;

This code works under 16bit cpu mode!

EDIT: To prevent zero shift first check if k = 0

 asm
      mov    cx, k         //ecx for 32bit cpu mode
      and    cl, cl        //zero test  
      jz     @Done
@1:
      clc
      sal    n, 1
      loop   @1
@Done:
 end;
GJ
that still doesn't work for me
Roy McAvoy
To prevent zero shift first check if k = 0 in your case cl or cx register. Look upper example!
GJ
Ok so first thank you for your help and suggestions. Second I still get the same error with your code
Roy McAvoy
Even with that it is still getting changed to 0
Roy McAvoy
At me works fine! So did you set result "sar:=n;" at the end of function?
GJ
yes i did that for both sar and sal but it has no effect
Roy McAvoy
I suppose you are Delphi user so show code!
GJ