Assembly 如何使用ARM汇编代码除以8?

Assembly 如何使用ARM汇编代码除以8?,assembly,arm,divide,thumb,Assembly,Arm,Divide,Thumb,我必须完成下面的程序框架,才能计算出数据区域中可除值的总和 并将结果存储在寄存器r5中。我的程序必须能够处理任意数量的数据值 (在内存和32位整数范围限制内),用户必须能够仅更改值 在数据区,程序将继续正常工作 THUMB AREA RESET, DATA, READONLY EXPORT Vectors EXPORT Reset_Handler Vectors DCD 0x20001000 ; top of the stack DCD Reset

我必须完成下面的程序框架,才能计算出数据区域中可除值的总和 并将结果存储在寄存器r5中。我的程序必须能够处理任意数量的数据值 (在内存和32位整数范围限制内),用户必须能够仅更改值 在数据区,程序将继续正常工作

    THUMB
    AREA RESET, DATA, READONLY
    EXPORT Vectors
    EXPORT Reset_Handler
Vectors
    DCD 0x20001000 ; top of the stack
    DCD Reset_Handler ; reset vector - where the program starts
    AREA Task2Code, CODE, READONLY
    ENTRY
Reset_Handler
num EQU 51
    MOV r1,#0
    MOV r5,#0
    LDR r8,=sum_up
loop
    MOV r2, r1, ROR #3 ; divide by 8
    LDR r2,[r8],#4
    ADD r5,r5,r2
    ADD r1,r1,#1
    CMP r1,#num
    B loop
terminate
    B terminate
sum_up
    DCD -16,100,-456,7,-123,-42,126789,2349,-34,-2344,45,-45,-3345 ; example values
    END

这是我到目前为止编写的代码,但我无法运行它,也不知道如何正确地除以8,有人对此有什么想法吗?

旋转显然不正确,它会将低位向上移动到符号位位置

您需要右移,如
MOV r2,r1,ASR#3
,又称
ASR r2,r1,#3

或者你需要有符号的整数除法,它和C有相同的向零的舍入行为吗?(算术右移向-无穷大舍入,但C型整数除法向零舍入。)

如果是这样,您可以像编译器一样实现它,使用符号位作为更正。另请参见此x86示例

或者只是:

gcc-O3-mcpu=cortex-m4(拇指模式asm):

clang的code gen稍微紧凑一些,但我认为所有16位指令都不需要
it
来断言其中一条指令:

div8(int):
    asrs    r1, r0, #31            @ copy the sign bit to all bits of r1
    add.w   r0, r0, r1, lsr #29    @ add 0 or 7 (logical shift right of all-ones or zeros)
    asrs    r0, r0, #3             @ r0 >>= 3
    bx      lr

旋转显然是不对的,它会将低位向上移动到符号位位置

您需要右移,如
MOV r2,r1,ASR#3
,又称
ASR r2,r1,#3

或者你需要有符号的整数除法,它和C有相同的向零的舍入行为吗?(算术右移向-无穷大舍入,但C型整数除法向零舍入。)

如果是这样,您可以像编译器一样实现它,使用符号位作为更正。另请参见此x86示例

或者只是:

gcc-O3-mcpu=cortex-m4(拇指模式asm):

clang的code gen稍微紧凑一些,但我认为所有16位指令都不需要
it
来断言其中一条指令:

div8(int):
    asrs    r1, r0, #31            @ copy the sign bit to all bits of r1
    add.w   r0, r0, r1, lsr #29    @ add 0 or 7 (logical shift right of all-ones or zeros)
    asrs    r0, r0, #3             @ r0 >>= 3
    bx      lr
来自@Peter Cordes的数据在使用移位进行分割方面是全面而准确的。但是,要完成任务(“计算数据区域中可被8整除的值之和”),实际上不需要被8整除。你只需要测试一个数字是否可以被8整除

您可能知道,任何可被8整除的数字的最低有效三位在其二进制表示中为零,就像任何可被1000整除的数字在十进制中的最后三位为零一样。幸运的是,这包括二进制中的负数——这只是2的补码算法的一个额外功能。因此,您的任务归结为测试每个数字的最低有效三位是否都为零。如果是,那么这个数字可以被8整除;如果不是,那就不是

要实现这一点,您需要的指令是
TST
。此指令有效地对其参数执行按位AND操作,并根据结果设置状态标志,但随后丢弃结果本身。它就像一个没有目标寄存器的ANDS。通过使用值为0x7(二进制111)的
TST
作为一个参数,如果另一个操作数可被8整除,则结果为零,否则结果为非零;因此,如果另一个操作数可被8整除,则将设置零标志,否则将清除该标志

例如:

loop
    ; (somehow obtain the next number in r4 here)
    TST r4, #0x7
    BNE loop        ; If the value in r4 is not divisible by 8, continue
    ADD r5, r5, r4  ; Add the value in r4 to the sum in r5
    B loop
这个例子显然是不完整的(没有实现将值加载到r4中,并且最终的分支是无条件的),但希望它能给您一个开始的地方。

from@Peter Cordes在使用移位进行除法方面是全面而准确的。但是,要完成任务(“计算数据区域中可被8整除的值之和”),实际上不需要被8整除。你只需要测试一个数字是否可以被8整除

您可能知道,任何可被8整除的数字的最低有效三位在其二进制表示中为零,就像任何可被1000整除的数字在十进制中的最后三位为零一样。幸运的是,这包括二进制中的负数——这只是2的补码算法的一个额外功能。因此,您的任务归结为测试每个数字的最低有效三位是否都为零。如果是,那么这个数字可以被8整除;如果不是,那就不是

要实现这一点,您需要的指令是
TST
。此指令有效地对其参数执行按位AND操作,并根据结果设置状态标志,但随后丢弃结果本身。它就像一个没有目标寄存器的ANDS。通过使用值为0x7(二进制111)的
TST
作为一个参数,如果另一个操作数可被8整除,则结果为零,否则结果为非零;因此,如果另一个操作数可被8整除,则将设置零标志,否则将清除该标志

例如:

loop
    ; (somehow obtain the next number in r4 here)
    TST r4, #0x7
    BNE loop        ; If the value in r4 is not divisible by 8, continue
    ADD r5, r5, r4  ; Add the value in r4 to the sum in r5
    B loop

这个例子显然是不完整的(没有实现将值加载到r4中,并且最终分支是无条件的),但希望它能给您一个开始的地方。

旋转不是分割。轮班是。非常感谢你们,你们觉得我该怎么做呢?轮班不是除法。轮班是。非常感谢,那么我该怎么做呢?@老定时器:是的,可能不是,我只是有点好奇ARM上的编译器将使用什么进行签名除法。@老定时器:是的,可能不是,我只是有点好奇ARM上的编译器将使用什么进行签名除法。噢,哇,我只阅读了代码中的问题标题和注释说明。事实证明,真正的问题是完全不同的!如果它没有改变,我也误解了它,仍然是一个元素