assembly 在AVR Studio中使用汇编确保寄存器中的值是否为3的乘积

gab6jxml  于 2023-04-21  发布在  其他
关注(0)|答案(1)|浏览(111)

我想确保如果一个数字在寄存器是一个乘法3使用avr工作室和asm语言,但在avr8515所以没有div语法
我已经尝试了一对夫妇的方法,如添加寄存器和0b0011期待进位标志将被设置,但它不是

tzxcd3kk

tzxcd3kk1#

因此,一种直接的方法是让avr-gcc编译一段C代码,然后查看它生成的assembly 1:
对于8位无符号值,请考虑以下C99:

#include <stdint.h>
#include <stdbool.h>

bool is_udiv3_8 (uint8_t x)
{
    return x % 3 == 0;
}

就像

> avr-gcc x.c -mmcu=atmega8515 -O2 -S

我们得到x.s(或者,将-save-temps添加到普通编译中,然后截取 *.s文件)。

is_udiv3_8:
    ldi r25,lo8(-85) ;1
    mul r24,r25      ;2
    mov r25,r1       ;3
    clr __zero_reg__ ;4
    lsr r25          ;5
    mov r18,r25      ;6
    lsl r18          ;7
    add r25,r18      ;8
    ldi r18,lo8(1)   ;9
    cpse r24,r25     ;10
    ldi r18,0        ;11
    mov r24,r18      ;12
    ret

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整除。
在汇编中编写:

  • 首先,对比特进行循环以获得二进制交叉和。为了速度,您将展开该循环,这将获得8 sbrs s和8 sbrc s。
  • 交叉和q满足-8〈= q〈= 8。求反不会改变q是否可被3整除,因此继续|q|这是非负的。
  • 减去3,直到结果为0、1或2。
  • 如果值达到0,则返回True,否则返回False(达到1或2)。
.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请注意,有不同的汇编语言。这个答案使用GNU assemlby方言,因为它与GNU汇编程序兼容,由avr-gcc和avr-g++生成。
2结果实际上更强:一个自然数N在模B +1中属于相同的剩余类,就像N在基B中的交错交叉和一样。

相关问题