.text
.global is_div3_asm
is_div3_asm:
;; R26 holds R25:R24 mod 3
clr r26
.Loop_bits:
;; Loop over all bits of R25:R24 to compute the alternating cross sum
;; over the binary digits of R25:R24.
sbiw r24, 0
breq .Loop_done
sbrc r24, 0 $ inc r26
sbrc r24, 1 $ dec r26
lsr r25 $ ror r24
lsr r25 $ ror r24
rjmp .Loop_bits
.Loop_done:
;; r26 = abs(r26)
sbrc r26, 7
neg r26
;; Now we have 0 <= r26 <= 8, so reduce to r26 < 3...
cpi r26, 3
brlt .Ltobool
subi r26, 3
;; ...now we have 0 <= r26 <= 5, so at most one more sub 3 will do.
cpi r26, 3
brlt .Ltobool
subi r26, 3
.Ltobool:
;; Return a bool in R24 as of avr-gcc ABI.
ldi r24, 1 ; True
cpi r26, 0
breq .Ldone
ldi r24, 0 ; False
.Ldone:
ret
此函数符合avr-gcc ABI和调用约定。您可以通过原型从C/C++使用它
extern bool is_div3_asm (uint16_t); // C
extern "C" bool is_div3_asm (uint16_t); // C++
1条答案
按热度按时间tzxcd3kk1#
因此,一种直接的方法是让avr-gcc编译一段C代码,然后查看它生成的assembly 1:
对于8位无符号值,请考虑以下C99:
就像
我们得到
x.s
(或者,将-save-temps
添加到普通编译中,然后截取 *.s文件)。avr-gcc所做的是将输入与-256/3相乘,并将乘积的高字节作为除以3后的商。经过一些调整后,如果输入可被3整除,则在R24中返回True(1),否则返回False(0)。
您可以将其扩展到16位值,但需要16×16=32乘法的高位字。
这时你就记住了,一个以B为底的自然数N能被B+1整除当且仅当以B为底的数的交错和能被B+1整除.
例如,在碱基B=2中:自然数N可被3整除当且仅当N的位的交错和可被3整除。
在汇编中编写:
sbrs
s和8sbrc
s。此函数符合avr-gcc ABI和调用约定。您可以通过原型从C/C++使用它
1请注意,有不同的汇编语言。这个答案使用GNU assemlby方言,因为它与GNU汇编程序兼容,由avr-gcc和avr-g++生成。
2结果实际上更强:一个自然数N在模B +1中属于相同的剩余类,就像N在基B中的交错交叉和一样。