News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

BSF reality

Started by dsouza123, March 05, 2006, 02:49:11 PM

Previous topic - Next topic

dsouza123

Code I wrote wasn't doing what I expected, so ran it through OllyDbg
with supprising results from the BSF instruction, so I created a short piece of test code.

Refrencing the Opcodes Help file that comes with MASM32,
the BSF entry info doesn't agree with the results
of test code stepped through with OllyDbg.

From the help file:
Sets ZF if a bit is found set and loads the destination with an index to first set bit.
Clears ZF is (-if-) no bits are found set.

It appears the status of the ZF (zero flag) is the opposite of the help file,
if OllyDbg (version 1.0.10.0) is correct.

Experimentally:
Clears ZF if a bit is found set...index to first set bit.  ( Clears ZF means ZF is 0. )
Sets ZF if no bits are found set.  Destination unchanged.

Given
ecx has 255
eax has any of 0,1,2,4
bsf ecx, eax

What are the correct final values of ecx and ZF (zero flag) ?

  mov ecx, 255
  mov eax, 0
  bsf ecx, eax

  mov ecx, 255
  mov eax, 1
  bsf ecx, eax

  mov ecx, 255
  mov eax, 2
  bsf ecx, eax

  mov ecx, 255
  mov eax, 4
  bsf ecx, eax

--Before--
eax ecx ZF
0   255 ?
1   255 ?
2   255 ?
4   255 ?

--After--
eax ecx ZF
0   255 1
1   0   0
2   1   0
4   2   0


Which is correct Opcode Help or OllyDbg ?
Any other tips/info on the BSF instruction ?

PBrennick

dsouza123,
QuoteThe BSF instruction scans for the first set bit (starting from bit position zero) in the source operand. The BSR instruction scans for the last set bit in the source operand by scanning from the H.O. bit towards the L.O. bit. If these instructions find a bit that is set in the source operand then they clear the zero flag and put the bit position into the destination register. If the source register contains zero (i.e., there are no set bits) then these instructions set the zero flag and leave an indeterminate value in the destination register. Note that you should test the zero flag immediately after the execution of these instructions to validate the destination register's value.

That is from my records, I don't remember where I got it.  As you can see, there is an error in the help file and olly is correct.  You have done a good job here and this is a good example of how it is not a good idea to take everything you read as gospel.  Testing, as you have done here, is always best when results look suspicious or unexpected.  Nice job and thank you for telling us.

Paul
The GeneSys Project is available from:
The Repository or My crappy website

dsouza123

Thanks for the clarifying and quick reply.

I was beginning to think I had the meanings set/clear reversed.

This errata got me thinking, with more elaborate test code
it could almost be decided, ( still depends on the definition of set/clear).


.data
  szClr      db "ZF is clr ( 0 ).", 0
  szSet      db "ZF is set ( 1 ).", 0

.code
  mov ecx, 255
  mov eax, 0
  bsf ecx, eax
  .if ZERO?
     invoke MessageBox, NULL, addr szSet, addr szSet, MB_OK
  .else
     invoke MessageBox, NULL, addr szClr, addr szClr, MB_OK
  .endif

  mov ecx, 255
  mov eax, 4
  bsf ecx, eax
  .if ZERO?
     invoke MessageBox, NULL, addr szSet, addr szSet, MB_OK
  .else
     invoke MessageBox, NULL, addr szClr, addr szClr, MB_OK
  .endif

PBrennick

dsouza123,
I am sure this is a kind of accidental typo by Hutch.  I'll bet with his package getting so large that he spends a lot of hours on it.  More people should thank him for his efforts.

Paul
The GeneSys Project is available from:
The Repository or My crappy website

Ratch

dsouza123,

    From the 386DX Programmers Reference Manual for the BSF instruction:

Flags Affected

"The ZF flag is set if all bits are 0; otherwise, the ZF flag is cleared."  Ratch

donkey

Not sure which x86 reference you are using, I use mainly x86eas.hlp which is excellent, it has essentially what Ratch says...

QuoteFlags Affected

The ZF flag is set to 1 if all the source operand is 0; otherwise, the ZF flag is cleared. The CF, OF, SF, AF, and PF, flags are undefined.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

PBrennick

Donkey,
Don't just read it, test it.  Any reference, no matter how excellent can have errors and then this causes a snowball effect.  Everyone copies the same reference and ...

The results of the tests done by dsouza123 cannot be denied or is the assemble and the dissassembler wrong, now?  I am not trying to sound harsh here but the tests...  How do you explain them?  I know that there is just as much a chance that my quote could be wrong also.  I am certainly no genius.  But the tests....

Paul
The GeneSys Project is available from:
The Repository or My crappy website

PBrennick

I just pulled my closet apart and found my copy of the Assembly language Quick reference by QUE.  It says I am wrong.  I will post what it says in 5 minutes.  Sorry.

Paul

The GeneSys Project is available from:
The Repository or My crappy website

donkey

Hi PBrennick,

I did test before I replied, the reference is correct...

mov eax,0
bsf eax,eax
DumpEFlags

Result = EFLAGS = PF ZF IF

mov eax,15
bsf eax,eax
DumpEFlags

Result = EFLAGS = PF IF

Seems perfectly fine to me.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

PBrennick

Donkey,
This is what QUE says...

QuoteBSR,
Bit Scan Reverse: BSR scans the bits of the second operand (starting with the high-order bit) to see whether any are set.  If all bits are clear (second operand is zero) the first operand is not changed and the zero flag is set. If any bit is set, the zero flag is cleared, and the first operand is set equal to the bit number of the bit that is set.

BSF, of course says essentially the same thing.

How could I be so dense?  I think my knowledge is slipping and maybe I should stop posting so much.
Paul
The GeneSys Project is available from:
The Repository or My crappy website

donkey

Hi Paul,

Just bad data in the original post, never liked debuggers for that express purpose so I wrote my own test routines that don't screw with the flags. My results for his test were...

mov ecx, 255
mov eax, 0
bsf ecx, eax
DumpEFlags

mov ecx, 255
mov eax, 1
bsf ecx, eax
DumpEFlags

mov ecx, 255
mov eax, 2
bsf ecx, eax
DumpEFlags

mov ecx, 255
mov eax, 4
bsf ecx, eax
DumpEFlags

EFLAGS = PF ZF IF
EFLAGS = PF IF
EFLAGS = PF IF
EFLAGS = PF IF


Which matches the documentation exactly.

Edgar.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

PBrennick

Yes I see that.  Also, I did not even take my own advice.  I trusted his results.  Not very professional, I think.

Paul
The GeneSys Project is available from:
The Repository or My crappy website

dsouza123

Thank you everyone for the clarifications and info.
Also learned about another very good opcode reference, x86eas.hlp. 
The more the better. :thumbu

So the results table from the test code originally posted are (mostly) correct.
Source 0 -> ZF == 1, Dest indeterminate.  (I listed the debugger result of unchanged.)
Source ~0 -> ZF == 0, Dest pos of low bit set.


--Before--
eax ecx ZF
0   255 ?
1   255 ?
2   255 ?
4   255 ?

--After--
eax ecx ZF
0   255 1     should be  0  ??? 1,  ecx should be indeterminate.
1   0   0
2   1   0
4   2   0