Whats wrong with my ARM assembly code for counting the number of 0's in a 32 bit register











up vote
0
down vote

favorite












test:
mov r1,#32

loop:
cmp r0, #0

beq done
mov r3, r0
lsr r0, r0, #1
cmp r0, r3
blt sub
b done
sub:

sub r1, r1, #1
b loop
done:

mov r0, r1
mov pc, lr


I have it set up so it decrements whenever there is a one present, but it doesnt quite work and I don't know why










share|improve this question
























  • It's unclear what your algorithm is. I don't see how blt helps you check for a 1 bit. I suggest you simply do and r3, r0, #1; sub r1, r1, r3; lsr r0, r0, #1; b loop.
    – Jester
    Nov 21 at 20:23










  • @Jester: blt could check the sign bit after a left-shift, like add r0, r0, r0 / cmp/ addlt r1, r1, #1. Or better, left-shift and set flags with adds / addmi to increment a counter when the bit is set. (Or I forget the condition name for non-negative, the opposite of MInus, which you could use with a conditional add to count zeros.) Or maybe you do need to subtract from 32 if you want to stop the loop when you've shifted out all the bits.
    – Peter Cordes
    Nov 21 at 20:27








  • 1




    I think you can count zeros in a sneaky, efficient way: shift your register one way or the other (doesn't matter); increment a counter if CARRY is set, and then leave the loop when your register is zero. This counts the number of 1 bits, stopping when they've all been shifted out and counted. Then you subtract the number of ones from 32 to get your answer.
    – Dave M.
    Nov 21 at 20:36










  • @DaveM Agree this is a good way to do it, but wouldn't call it "sneaky" at all.
    – TypeIA
    Nov 21 at 20:57















up vote
0
down vote

favorite












test:
mov r1,#32

loop:
cmp r0, #0

beq done
mov r3, r0
lsr r0, r0, #1
cmp r0, r3
blt sub
b done
sub:

sub r1, r1, #1
b loop
done:

mov r0, r1
mov pc, lr


I have it set up so it decrements whenever there is a one present, but it doesnt quite work and I don't know why










share|improve this question
























  • It's unclear what your algorithm is. I don't see how blt helps you check for a 1 bit. I suggest you simply do and r3, r0, #1; sub r1, r1, r3; lsr r0, r0, #1; b loop.
    – Jester
    Nov 21 at 20:23










  • @Jester: blt could check the sign bit after a left-shift, like add r0, r0, r0 / cmp/ addlt r1, r1, #1. Or better, left-shift and set flags with adds / addmi to increment a counter when the bit is set. (Or I forget the condition name for non-negative, the opposite of MInus, which you could use with a conditional add to count zeros.) Or maybe you do need to subtract from 32 if you want to stop the loop when you've shifted out all the bits.
    – Peter Cordes
    Nov 21 at 20:27








  • 1




    I think you can count zeros in a sneaky, efficient way: shift your register one way or the other (doesn't matter); increment a counter if CARRY is set, and then leave the loop when your register is zero. This counts the number of 1 bits, stopping when they've all been shifted out and counted. Then you subtract the number of ones from 32 to get your answer.
    – Dave M.
    Nov 21 at 20:36










  • @DaveM Agree this is a good way to do it, but wouldn't call it "sneaky" at all.
    – TypeIA
    Nov 21 at 20:57













up vote
0
down vote

favorite









up vote
0
down vote

favorite











test:
mov r1,#32

loop:
cmp r0, #0

beq done
mov r3, r0
lsr r0, r0, #1
cmp r0, r3
blt sub
b done
sub:

sub r1, r1, #1
b loop
done:

mov r0, r1
mov pc, lr


I have it set up so it decrements whenever there is a one present, but it doesnt quite work and I don't know why










share|improve this question















test:
mov r1,#32

loop:
cmp r0, #0

beq done
mov r3, r0
lsr r0, r0, #1
cmp r0, r3
blt sub
b done
sub:

sub r1, r1, #1
b loop
done:

mov r0, r1
mov pc, lr


I have it set up so it decrements whenever there is a one present, but it doesnt quite work and I don't know why







assembly count arm counter bit






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 at 20:27









Peter Cordes

116k16177304




116k16177304










asked Nov 21 at 20:13









user10687771

1




1












  • It's unclear what your algorithm is. I don't see how blt helps you check for a 1 bit. I suggest you simply do and r3, r0, #1; sub r1, r1, r3; lsr r0, r0, #1; b loop.
    – Jester
    Nov 21 at 20:23










  • @Jester: blt could check the sign bit after a left-shift, like add r0, r0, r0 / cmp/ addlt r1, r1, #1. Or better, left-shift and set flags with adds / addmi to increment a counter when the bit is set. (Or I forget the condition name for non-negative, the opposite of MInus, which you could use with a conditional add to count zeros.) Or maybe you do need to subtract from 32 if you want to stop the loop when you've shifted out all the bits.
    – Peter Cordes
    Nov 21 at 20:27








  • 1




    I think you can count zeros in a sneaky, efficient way: shift your register one way or the other (doesn't matter); increment a counter if CARRY is set, and then leave the loop when your register is zero. This counts the number of 1 bits, stopping when they've all been shifted out and counted. Then you subtract the number of ones from 32 to get your answer.
    – Dave M.
    Nov 21 at 20:36










  • @DaveM Agree this is a good way to do it, but wouldn't call it "sneaky" at all.
    – TypeIA
    Nov 21 at 20:57


















  • It's unclear what your algorithm is. I don't see how blt helps you check for a 1 bit. I suggest you simply do and r3, r0, #1; sub r1, r1, r3; lsr r0, r0, #1; b loop.
    – Jester
    Nov 21 at 20:23










  • @Jester: blt could check the sign bit after a left-shift, like add r0, r0, r0 / cmp/ addlt r1, r1, #1. Or better, left-shift and set flags with adds / addmi to increment a counter when the bit is set. (Or I forget the condition name for non-negative, the opposite of MInus, which you could use with a conditional add to count zeros.) Or maybe you do need to subtract from 32 if you want to stop the loop when you've shifted out all the bits.
    – Peter Cordes
    Nov 21 at 20:27








  • 1




    I think you can count zeros in a sneaky, efficient way: shift your register one way or the other (doesn't matter); increment a counter if CARRY is set, and then leave the loop when your register is zero. This counts the number of 1 bits, stopping when they've all been shifted out and counted. Then you subtract the number of ones from 32 to get your answer.
    – Dave M.
    Nov 21 at 20:36










  • @DaveM Agree this is a good way to do it, but wouldn't call it "sneaky" at all.
    – TypeIA
    Nov 21 at 20:57
















It's unclear what your algorithm is. I don't see how blt helps you check for a 1 bit. I suggest you simply do and r3, r0, #1; sub r1, r1, r3; lsr r0, r0, #1; b loop.
– Jester
Nov 21 at 20:23




It's unclear what your algorithm is. I don't see how blt helps you check for a 1 bit. I suggest you simply do and r3, r0, #1; sub r1, r1, r3; lsr r0, r0, #1; b loop.
– Jester
Nov 21 at 20:23












@Jester: blt could check the sign bit after a left-shift, like add r0, r0, r0 / cmp/ addlt r1, r1, #1. Or better, left-shift and set flags with adds / addmi to increment a counter when the bit is set. (Or I forget the condition name for non-negative, the opposite of MInus, which you could use with a conditional add to count zeros.) Or maybe you do need to subtract from 32 if you want to stop the loop when you've shifted out all the bits.
– Peter Cordes
Nov 21 at 20:27






@Jester: blt could check the sign bit after a left-shift, like add r0, r0, r0 / cmp/ addlt r1, r1, #1. Or better, left-shift and set flags with adds / addmi to increment a counter when the bit is set. (Or I forget the condition name for non-negative, the opposite of MInus, which you could use with a conditional add to count zeros.) Or maybe you do need to subtract from 32 if you want to stop the loop when you've shifted out all the bits.
– Peter Cordes
Nov 21 at 20:27






1




1




I think you can count zeros in a sneaky, efficient way: shift your register one way or the other (doesn't matter); increment a counter if CARRY is set, and then leave the loop when your register is zero. This counts the number of 1 bits, stopping when they've all been shifted out and counted. Then you subtract the number of ones from 32 to get your answer.
– Dave M.
Nov 21 at 20:36




I think you can count zeros in a sneaky, efficient way: shift your register one way or the other (doesn't matter); increment a counter if CARRY is set, and then leave the loop when your register is zero. This counts the number of 1 bits, stopping when they've all been shifted out and counted. Then you subtract the number of ones from 32 to get your answer.
– Dave M.
Nov 21 at 20:36












@DaveM Agree this is a good way to do it, but wouldn't call it "sneaky" at all.
– TypeIA
Nov 21 at 20:57




@DaveM Agree this is a good way to do it, but wouldn't call it "sneaky" at all.
– TypeIA
Nov 21 at 20:57












1 Answer
1






active

oldest

votes

















up vote
1
down vote













Your design idea is somewhat overcomplicated, which made it harder for you to get the code right. I'm not sure exactly why you thought (x>>1) < x (signed compare after unsigned right shift) was useful.



You can take advantage of flags to get information about the top bit, but you don't need a cmp do to so. Use a left-shift (or add same,same) that sets flags, and test the S flag using the MInus condition to find out what the high bit of the result was.



Or look at the C flag to see the bit shifted out, but then you'd need to do something with the C flag after the last iteration (after the register becomes zero). That's fine, you can peel out that last iteration.



Using a right shift (your lsr) can't work if you're using conditions that depend on the sign bit.





test:
movs r1, r0 @ copy and set flags
mov r0, #32

@ loop invariants:
@ r0 = return value
@ r1 = input
@ flags set according to the current value of r1
.loop: @ do {
submi r0, r0, #1 @ predicated subtract: if(high_bit_set(r1)) r0--;
adds r1, r1 @ left-shift by 1 and set flags
bne .loop @ keep looping until there are no set bits
@ }while(r1<<=1);

mov pc, lr @ or bx lr


Instead of branching, you definitely want to take advantage of ARM's predicated execution of any instruction, but appending a condition to the mnemonic. submi is a sub which is a no-op if the MI condition is false.





Of course if you care about performance, an 8-bit lookup table can be a good way to implement popcnt, or there's a bithack formula that ARM can probably do very efficiently with its barrel shifter. How to count the number of set bits in a 32-bit integer?



AFAIK, ARM doesn't have a hardware bit-count instruction like some other architectures do, e.g. x86's popcnt.



In computer programs, small numbers are usually common. Left-shifting will take ~30 iterations to shift out all the bits for numbers with any low bits set. But right-shifting can finish in a few iterations for small numbers like 7 (only the low 3 bits set).



If it's common for your inputs to have some contiguous high bits all cleared, then the left-shifting loop I wrote for this answer is the worst.






share|improve this answer





















  • Great answer. Just to note that ROR and RRX do (or can) affect the carry flag, so it's not completely true that using a right shift can't work if your conditions depend on the carry flag, though admittedly they're not much use in this context. (That said, maybe an RRX with the rest of the code crafted such that the carry flag is guaranteed zero on entry to the RRX could be made to work...)
    – cooperised
    Nov 21 at 22:25










  • @cooperised: yeah, rotate is interesting, but then the register will never become zero. Anyway, note that I said LSR can't work if you're looking at the sign bit / flag. The OP is using cmp after the shift, destroying any C. So yes, LSR to shift the low bit into carry would be good, with a final add or sub after the loop exit. (Like subc r0, r0, #1 / lsrs r1,r1,#1 / bne, then subc r0,r0,#1 / ret. Or whatever the right name is for a condition that's true if C is set. I know ARM is different than x86 for some condition names.)
    – Peter Cordes
    Nov 21 at 22:35










  • Agreed. The register will become zero using RRX if you ensure that the carry flag is clear before each use though. Not the most readable code, perhaps, but feasible :-D
    – cooperised
    Nov 22 at 10:05











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53419817%2fwhats-wrong-with-my-arm-assembly-code-for-counting-the-number-of-0s-in-a-32-bit%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote













Your design idea is somewhat overcomplicated, which made it harder for you to get the code right. I'm not sure exactly why you thought (x>>1) < x (signed compare after unsigned right shift) was useful.



You can take advantage of flags to get information about the top bit, but you don't need a cmp do to so. Use a left-shift (or add same,same) that sets flags, and test the S flag using the MInus condition to find out what the high bit of the result was.



Or look at the C flag to see the bit shifted out, but then you'd need to do something with the C flag after the last iteration (after the register becomes zero). That's fine, you can peel out that last iteration.



Using a right shift (your lsr) can't work if you're using conditions that depend on the sign bit.





test:
movs r1, r0 @ copy and set flags
mov r0, #32

@ loop invariants:
@ r0 = return value
@ r1 = input
@ flags set according to the current value of r1
.loop: @ do {
submi r0, r0, #1 @ predicated subtract: if(high_bit_set(r1)) r0--;
adds r1, r1 @ left-shift by 1 and set flags
bne .loop @ keep looping until there are no set bits
@ }while(r1<<=1);

mov pc, lr @ or bx lr


Instead of branching, you definitely want to take advantage of ARM's predicated execution of any instruction, but appending a condition to the mnemonic. submi is a sub which is a no-op if the MI condition is false.





Of course if you care about performance, an 8-bit lookup table can be a good way to implement popcnt, or there's a bithack formula that ARM can probably do very efficiently with its barrel shifter. How to count the number of set bits in a 32-bit integer?



AFAIK, ARM doesn't have a hardware bit-count instruction like some other architectures do, e.g. x86's popcnt.



In computer programs, small numbers are usually common. Left-shifting will take ~30 iterations to shift out all the bits for numbers with any low bits set. But right-shifting can finish in a few iterations for small numbers like 7 (only the low 3 bits set).



If it's common for your inputs to have some contiguous high bits all cleared, then the left-shifting loop I wrote for this answer is the worst.






share|improve this answer





















  • Great answer. Just to note that ROR and RRX do (or can) affect the carry flag, so it's not completely true that using a right shift can't work if your conditions depend on the carry flag, though admittedly they're not much use in this context. (That said, maybe an RRX with the rest of the code crafted such that the carry flag is guaranteed zero on entry to the RRX could be made to work...)
    – cooperised
    Nov 21 at 22:25










  • @cooperised: yeah, rotate is interesting, but then the register will never become zero. Anyway, note that I said LSR can't work if you're looking at the sign bit / flag. The OP is using cmp after the shift, destroying any C. So yes, LSR to shift the low bit into carry would be good, with a final add or sub after the loop exit. (Like subc r0, r0, #1 / lsrs r1,r1,#1 / bne, then subc r0,r0,#1 / ret. Or whatever the right name is for a condition that's true if C is set. I know ARM is different than x86 for some condition names.)
    – Peter Cordes
    Nov 21 at 22:35










  • Agreed. The register will become zero using RRX if you ensure that the carry flag is clear before each use though. Not the most readable code, perhaps, but feasible :-D
    – cooperised
    Nov 22 at 10:05















up vote
1
down vote













Your design idea is somewhat overcomplicated, which made it harder for you to get the code right. I'm not sure exactly why you thought (x>>1) < x (signed compare after unsigned right shift) was useful.



You can take advantage of flags to get information about the top bit, but you don't need a cmp do to so. Use a left-shift (or add same,same) that sets flags, and test the S flag using the MInus condition to find out what the high bit of the result was.



Or look at the C flag to see the bit shifted out, but then you'd need to do something with the C flag after the last iteration (after the register becomes zero). That's fine, you can peel out that last iteration.



Using a right shift (your lsr) can't work if you're using conditions that depend on the sign bit.





test:
movs r1, r0 @ copy and set flags
mov r0, #32

@ loop invariants:
@ r0 = return value
@ r1 = input
@ flags set according to the current value of r1
.loop: @ do {
submi r0, r0, #1 @ predicated subtract: if(high_bit_set(r1)) r0--;
adds r1, r1 @ left-shift by 1 and set flags
bne .loop @ keep looping until there are no set bits
@ }while(r1<<=1);

mov pc, lr @ or bx lr


Instead of branching, you definitely want to take advantage of ARM's predicated execution of any instruction, but appending a condition to the mnemonic. submi is a sub which is a no-op if the MI condition is false.





Of course if you care about performance, an 8-bit lookup table can be a good way to implement popcnt, or there's a bithack formula that ARM can probably do very efficiently with its barrel shifter. How to count the number of set bits in a 32-bit integer?



AFAIK, ARM doesn't have a hardware bit-count instruction like some other architectures do, e.g. x86's popcnt.



In computer programs, small numbers are usually common. Left-shifting will take ~30 iterations to shift out all the bits for numbers with any low bits set. But right-shifting can finish in a few iterations for small numbers like 7 (only the low 3 bits set).



If it's common for your inputs to have some contiguous high bits all cleared, then the left-shifting loop I wrote for this answer is the worst.






share|improve this answer





















  • Great answer. Just to note that ROR and RRX do (or can) affect the carry flag, so it's not completely true that using a right shift can't work if your conditions depend on the carry flag, though admittedly they're not much use in this context. (That said, maybe an RRX with the rest of the code crafted such that the carry flag is guaranteed zero on entry to the RRX could be made to work...)
    – cooperised
    Nov 21 at 22:25










  • @cooperised: yeah, rotate is interesting, but then the register will never become zero. Anyway, note that I said LSR can't work if you're looking at the sign bit / flag. The OP is using cmp after the shift, destroying any C. So yes, LSR to shift the low bit into carry would be good, with a final add or sub after the loop exit. (Like subc r0, r0, #1 / lsrs r1,r1,#1 / bne, then subc r0,r0,#1 / ret. Or whatever the right name is for a condition that's true if C is set. I know ARM is different than x86 for some condition names.)
    – Peter Cordes
    Nov 21 at 22:35










  • Agreed. The register will become zero using RRX if you ensure that the carry flag is clear before each use though. Not the most readable code, perhaps, but feasible :-D
    – cooperised
    Nov 22 at 10:05













up vote
1
down vote










up vote
1
down vote









Your design idea is somewhat overcomplicated, which made it harder for you to get the code right. I'm not sure exactly why you thought (x>>1) < x (signed compare after unsigned right shift) was useful.



You can take advantage of flags to get information about the top bit, but you don't need a cmp do to so. Use a left-shift (or add same,same) that sets flags, and test the S flag using the MInus condition to find out what the high bit of the result was.



Or look at the C flag to see the bit shifted out, but then you'd need to do something with the C flag after the last iteration (after the register becomes zero). That's fine, you can peel out that last iteration.



Using a right shift (your lsr) can't work if you're using conditions that depend on the sign bit.





test:
movs r1, r0 @ copy and set flags
mov r0, #32

@ loop invariants:
@ r0 = return value
@ r1 = input
@ flags set according to the current value of r1
.loop: @ do {
submi r0, r0, #1 @ predicated subtract: if(high_bit_set(r1)) r0--;
adds r1, r1 @ left-shift by 1 and set flags
bne .loop @ keep looping until there are no set bits
@ }while(r1<<=1);

mov pc, lr @ or bx lr


Instead of branching, you definitely want to take advantage of ARM's predicated execution of any instruction, but appending a condition to the mnemonic. submi is a sub which is a no-op if the MI condition is false.





Of course if you care about performance, an 8-bit lookup table can be a good way to implement popcnt, or there's a bithack formula that ARM can probably do very efficiently with its barrel shifter. How to count the number of set bits in a 32-bit integer?



AFAIK, ARM doesn't have a hardware bit-count instruction like some other architectures do, e.g. x86's popcnt.



In computer programs, small numbers are usually common. Left-shifting will take ~30 iterations to shift out all the bits for numbers with any low bits set. But right-shifting can finish in a few iterations for small numbers like 7 (only the low 3 bits set).



If it's common for your inputs to have some contiguous high bits all cleared, then the left-shifting loop I wrote for this answer is the worst.






share|improve this answer












Your design idea is somewhat overcomplicated, which made it harder for you to get the code right. I'm not sure exactly why you thought (x>>1) < x (signed compare after unsigned right shift) was useful.



You can take advantage of flags to get information about the top bit, but you don't need a cmp do to so. Use a left-shift (or add same,same) that sets flags, and test the S flag using the MInus condition to find out what the high bit of the result was.



Or look at the C flag to see the bit shifted out, but then you'd need to do something with the C flag after the last iteration (after the register becomes zero). That's fine, you can peel out that last iteration.



Using a right shift (your lsr) can't work if you're using conditions that depend on the sign bit.





test:
movs r1, r0 @ copy and set flags
mov r0, #32

@ loop invariants:
@ r0 = return value
@ r1 = input
@ flags set according to the current value of r1
.loop: @ do {
submi r0, r0, #1 @ predicated subtract: if(high_bit_set(r1)) r0--;
adds r1, r1 @ left-shift by 1 and set flags
bne .loop @ keep looping until there are no set bits
@ }while(r1<<=1);

mov pc, lr @ or bx lr


Instead of branching, you definitely want to take advantage of ARM's predicated execution of any instruction, but appending a condition to the mnemonic. submi is a sub which is a no-op if the MI condition is false.





Of course if you care about performance, an 8-bit lookup table can be a good way to implement popcnt, or there's a bithack formula that ARM can probably do very efficiently with its barrel shifter. How to count the number of set bits in a 32-bit integer?



AFAIK, ARM doesn't have a hardware bit-count instruction like some other architectures do, e.g. x86's popcnt.



In computer programs, small numbers are usually common. Left-shifting will take ~30 iterations to shift out all the bits for numbers with any low bits set. But right-shifting can finish in a few iterations for small numbers like 7 (only the low 3 bits set).



If it's common for your inputs to have some contiguous high bits all cleared, then the left-shifting loop I wrote for this answer is the worst.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 21 at 20:53









Peter Cordes

116k16177304




116k16177304












  • Great answer. Just to note that ROR and RRX do (or can) affect the carry flag, so it's not completely true that using a right shift can't work if your conditions depend on the carry flag, though admittedly they're not much use in this context. (That said, maybe an RRX with the rest of the code crafted such that the carry flag is guaranteed zero on entry to the RRX could be made to work...)
    – cooperised
    Nov 21 at 22:25










  • @cooperised: yeah, rotate is interesting, but then the register will never become zero. Anyway, note that I said LSR can't work if you're looking at the sign bit / flag. The OP is using cmp after the shift, destroying any C. So yes, LSR to shift the low bit into carry would be good, with a final add or sub after the loop exit. (Like subc r0, r0, #1 / lsrs r1,r1,#1 / bne, then subc r0,r0,#1 / ret. Or whatever the right name is for a condition that's true if C is set. I know ARM is different than x86 for some condition names.)
    – Peter Cordes
    Nov 21 at 22:35










  • Agreed. The register will become zero using RRX if you ensure that the carry flag is clear before each use though. Not the most readable code, perhaps, but feasible :-D
    – cooperised
    Nov 22 at 10:05


















  • Great answer. Just to note that ROR and RRX do (or can) affect the carry flag, so it's not completely true that using a right shift can't work if your conditions depend on the carry flag, though admittedly they're not much use in this context. (That said, maybe an RRX with the rest of the code crafted such that the carry flag is guaranteed zero on entry to the RRX could be made to work...)
    – cooperised
    Nov 21 at 22:25










  • @cooperised: yeah, rotate is interesting, but then the register will never become zero. Anyway, note that I said LSR can't work if you're looking at the sign bit / flag. The OP is using cmp after the shift, destroying any C. So yes, LSR to shift the low bit into carry would be good, with a final add or sub after the loop exit. (Like subc r0, r0, #1 / lsrs r1,r1,#1 / bne, then subc r0,r0,#1 / ret. Or whatever the right name is for a condition that's true if C is set. I know ARM is different than x86 for some condition names.)
    – Peter Cordes
    Nov 21 at 22:35










  • Agreed. The register will become zero using RRX if you ensure that the carry flag is clear before each use though. Not the most readable code, perhaps, but feasible :-D
    – cooperised
    Nov 22 at 10:05
















Great answer. Just to note that ROR and RRX do (or can) affect the carry flag, so it's not completely true that using a right shift can't work if your conditions depend on the carry flag, though admittedly they're not much use in this context. (That said, maybe an RRX with the rest of the code crafted such that the carry flag is guaranteed zero on entry to the RRX could be made to work...)
– cooperised
Nov 21 at 22:25




Great answer. Just to note that ROR and RRX do (or can) affect the carry flag, so it's not completely true that using a right shift can't work if your conditions depend on the carry flag, though admittedly they're not much use in this context. (That said, maybe an RRX with the rest of the code crafted such that the carry flag is guaranteed zero on entry to the RRX could be made to work...)
– cooperised
Nov 21 at 22:25












@cooperised: yeah, rotate is interesting, but then the register will never become zero. Anyway, note that I said LSR can't work if you're looking at the sign bit / flag. The OP is using cmp after the shift, destroying any C. So yes, LSR to shift the low bit into carry would be good, with a final add or sub after the loop exit. (Like subc r0, r0, #1 / lsrs r1,r1,#1 / bne, then subc r0,r0,#1 / ret. Or whatever the right name is for a condition that's true if C is set. I know ARM is different than x86 for some condition names.)
– Peter Cordes
Nov 21 at 22:35




@cooperised: yeah, rotate is interesting, but then the register will never become zero. Anyway, note that I said LSR can't work if you're looking at the sign bit / flag. The OP is using cmp after the shift, destroying any C. So yes, LSR to shift the low bit into carry would be good, with a final add or sub after the loop exit. (Like subc r0, r0, #1 / lsrs r1,r1,#1 / bne, then subc r0,r0,#1 / ret. Or whatever the right name is for a condition that's true if C is set. I know ARM is different than x86 for some condition names.)
– Peter Cordes
Nov 21 at 22:35












Agreed. The register will become zero using RRX if you ensure that the carry flag is clear before each use though. Not the most readable code, perhaps, but feasible :-D
– cooperised
Nov 22 at 10:05




Agreed. The register will become zero using RRX if you ensure that the carry flag is clear before each use though. Not the most readable code, perhaps, but feasible :-D
– cooperised
Nov 22 at 10:05


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53419817%2fwhats-wrong-with-my-arm-assembly-code-for-counting-the-number-of-0s-in-a-32-bit%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

Calculate evaluation metrics using cross_val_predict sklearn

Insert data from modal to MySQL (multiple modal on website)