News:

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

Flag setting method

Started by Neil, November 06, 2010, 11:55:30 AM

Previous topic - Next topic

Neil

In my program I have a block of memory which are byte sized flags, either zero or one. There are a number of ways of setting & resetting these flags, here are some methods :-

esi is the pointer to the start of the flags, setting a flag can be done as follows where n is the position of the flag.

inc byte ptr [esi+n]

add byte ptr [esi+n],1

mov byte ptr [esi+n],1

or byte ptr [esi+n],1

restting the flag would be the opposite of this :-

dec byte ptr[esi+n]

sub byte ptr [esi+n],1

mov byte ptr [esi+],0

and byte ptr [esi+n],0

my query is which is the better (faster) method. Probably another method would be to treat each flag as a variable with a unique label. but then the same problem would arise as how to deal with them.

dedndave

from my experience, you have to try each one with the code that will surround it
i.e. the one that will be fastest may depend on adjacent instructions    :P
of all the instructions you show, i would lean toward the MOV's however - they are likely to be fastest
that is because, with the other instructions, the processor has to read and write the memory operand

also, in some cases, calculating the entire address in a single register may or may not help
that is, if you can stick some other instructions between the steps
you have to try it both ways and time it - lol
for example
        mov     ebx,n
;some other instruction(s)
        add     ebx,esi
;some other instruction(s)
        mov byte ptr [ebx],0

of course, if you have a register that happens to contain a 0, this is best
;al = 0
        mov     ebx,n
;some other instruction(s)
        add     ebx,esi
;some other instruction(s)
        mov     [ebx],al

or
;al = 0
        mov     [esi+n],al

using a register rather than an immediate is faster and smaller, too

reading your question, i get the impression that each section of code accesses one flag value
if you happen to be accessing the flag several times, it may be advantageous to place it in the stack frame
you can do that by calculating (n - (n mod 4)) and pushing the flag set
        mov     ebx,n
        and     bl,0FCh
        push dword ptr [esi+ebx]

;then access it with ebp

        mov     [ebp-m],al

;and store the flag set when done

        pop dword ptr [esi+ebx]


that method probably won't help you - but there are cases where it may
on a similar note, i have had cases where placing a dword constant in the stack frame was faster than coding it as an immediate
most modern processors are designed to optimize stack frame references

clive

The MOV is the only instruction listed that only WRITES, the others are READ-MODIFY-WRITE (RMW) type instructions. Most of the slowness is absorbed by the processor with caches, and write buffers these days, add a LOCK prefix to see how slow they are if the RMW operation is performed atomically.

The x86 also has the BTR and BTS instructions to test and reset/set bits.
It could be a random act of randomness. Those happen a lot as well.

Neil

Thanks Dave for your comments, you've given me something to think about.
Clive I hadn't thought of using BTR, BTS, I'll have to look into that, check clock cycles etc
Thanks guys  :U

dedndave

MOV's are probably still your best bet   :P

Neil

Yes, mov immediate seems to be the way to go, but first I'll check if any register contains zero, I have my doubts but still worth a look.

dedndave

i forgot to mention something...
memory likes to be accessed as 4-aligned dwords
again, if you are accessing the flag several times, and have a register available,
you may want to get 4 flags into, say, EDX at the onset
then access the flag in-register and store the result from EDX when finished

Neil

Yes, that's a good thought Dave, something else to look into. My next problem is to check whether the flags are zero or one, I seem to remember there was rather a long discussion on that very thing not so long ago   :toothy

Neil

Anyone know the link to the check for zero or one topic I can't find it. It got that involved I can't remember what the decision was, that's if there was one.

dedndave

lol - i think that thread was for in-register checks

but - give us some clues ????
i take it, upon entry, that the flag may be either 0 or 1
do you always clear it on exit ?

Neil

I can't remember, all I know is that it was a test for zero or one something along the lines of TEST EAX,EAX.
The flags can be either on entry & cleared or not cleared on exit.

dedndave

that being the case, i would try to get a 4-aligned dword into register
then use Clives suggestion of using bit test/set instructions on that register
if you don't clear it on exit, you simply do nothing   :bg

besides using MOV, that's really all i can think of

Neil

Yes, that's probably a good idea, but I'd still like to read that post to see if there was a decision. I've done lots of searches & come up blank, just a matter of finding the correct search parameters. I don't think it was that long ago, but, then again it could have been last year.

jj2007

If you need no more than 32 different flags, here two macros from the MasmBasic library:

Flags MACRO pos
  bt MbFlags, pos
  EXITM <CarrY?>
ENDM

SetFlags MACRO pos, mode
  .if mode
bts MbFlags, pos
  .else
btr MbFlags, pos
  .endif
ENDM


Usage:
include \masm32\MasmBasic\MasmBasic.inc
Init
Whatever = 3
SetFlags Whatever, 1
.if Flags(Whatever)
MsgBox 0, "Flag Whatever set", "Hi", MB_OK
.else
MsgBox 0, "Flag Whatever clear", "Hi", MB_OK
.endif
SetFlags Whatever, 0
.if Flags(Whatever)
MsgBox 0, "Flag Whatever set", "Hi", MB_OK
.else
MsgBox 0, "Flag Whatever clear", "Hi", MB_OK
.endif
Exit
end start

Neil

That's interesting jj, but unfortunately there are 100+ flags :(