I need to write the following C code snippet in 8086* assembly as short as possible (less than 10 bytes) but I can only manage to write it in 12 bytes.
any ideas?
while (ax) {
bx--;
ax &= ax-1;
}
I need to write the following C code snippet in 8086* assembly as short as possible (less than 10 bytes) but I can only manage to write it in 12 bytes.
any ideas?
while (ax) {
bx--;
ax &= ax-1;
}
The operation that you're attempting is called a population count, i.e. count the number of set bits in a register.
There is actually a single instruction for that in newer CPU's. And since targeting the orginal 8086 is really not that interesting in 2018.
The simple answer is:
f3 0f b8 c0 popcnt eax,eax
29 c3 sub ebx,eax
6 bytes, which can be reduced to 4 if you're willing to allow a positive value in ebx and can assume/assure that ebx is zero to begin with.
Note that there is no need to work with the 16-bit registers, there has not been for many years.
If you want the code to work on the original 8086 (which does not support popcnt) you'll have to retain the loop.
The following perfectly straightforward code takes 12 bytes:
85 c0 test ax,ax ;is AX zero?
74 08 je <done> ;yes, bail out
<loop>:
4b dec bx ;bx--
89 c1 mov cx,ax
49 dec cx ;cx = ax - 1
21 c8 and ax,cx ;ax = ax & (ax-1)
75 f8 jne <loop> ;repeat until done
<done>:
You can cut this down to 9 bytes by counting the bits in a slightly less efficient way. Here we simply test all 16 bits of ax.
<loop>:
d1 e0 shl ax,1 ;MSb to carry flag (CF)
83 db 00 sbb bx,0 ;bx=bx-CF
85 c0 test ax,ax ;is AX zero?
75 f9 jnz <loop> ;if not then loop until done
The trick is to understand what the code does and then rephrase it in a different way.