Armstorm – ARM Disassembler

Heya

It seems the distorm-arm project is going to be called Armstorm, after asking the guys on Twitter.
Anyway, as I’m working on this project, I just came up with the following cool snippet and wanted to submit it as a riddle:

int base = 0;
int runLength = 0;
while (mask && (~mask & 1)) base++, mask >>= 1;
while (mask && (mask & 1)) runLength++, mask >>= 1;
if (!mask && runLength > 2) {
...
}

Any idea what does it do or why I need it ?

8 Responses to “Armstorm – ARM Disassembler”

1. someone says:

find position of first 0 bit and first 1 bit in the mask?

2. arkon says:

Not really… because it continues to count even though it found a zero bit… until when?

3. Ofek Shilon says:

finds the location of the rightmost 1’s block (first while), and its length (second while).
The condition in the if ensures that this 1’s block was in fact the single one, of size at least 3.
Also, the second while condition can be shortened to ‘while (mask & 1)’.

Maybe its for analysis of R/M portions of opcodes?

4. arkon says:

Nice Ofek!

It could be really shortened, that what happens when you write code at 2:30 AM :)

I use this code to format a registers-list for some instructions. For example:

PUSH {R0-R7}
STMIA R0!, {R4-R6}

I want to show a sequence of more than 2 registers in the %d-%d format, and the rest will be separated (it wasn’t part of the snippet).

Suppose:
POP {R0, R5, R7}

Thumbs up ;)

5. Peter Ferrie says:

of course, it’s faster if you avoid checking mask==0 repeatedly:

if (mask)
{
int base = 0;
int runLength = 0;
while (~mask & 1) base++, mask >>= 1;
//mask is never zero here, always &1 initially
while (mask & 1) runLength++, mask >>= 1;
if (!mask && runLength > 2)
{

}
}

6. Peter Ferrie says:

actually, that first while should say !(mask & 1).
you don’t want to be performing ~mask every time, either.

7. arkon says:

Sweet, thanks.
I really like the (~mask & 1) -> !(mask & 1), I wonder if the compiler could know to do it on its own…

8. You will want to check the __builtin_ctz() function (for GCC) and/or _BitScanReverse() (for MSVC, iirc.)