Assembly 如何使用ARM汇编代码除以8?
我必须完成下面的程序框架,才能计算出数据区域中可除值的总和 并将结果存储在寄存器r5中。我的程序必须能够处理任意数量的数据值 (在内存和32位整数范围限制内),用户必须能够仅更改值 在数据区,程序将继续正常工作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
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上的编译器将使用什么进行签名除法。噢,哇,我只阅读了代码中的问题标题和注释说明。事实证明,真正的问题是完全不同的!如果它没有改变,我也误解了它,仍然是一个元素