Assembly 试图在手臂上分开得到奇怪的结果
我正在尝试在不使用ARM组件中的divide函数的情况下进行除法。我的代码如下。由于某种原因,结果一直保持在2400年代 我已尝试将以下伪代码写入arm: 在r0和r1中获取输入 将r1添加到r3,直到r3超过r0 增量计数器 从r3中减去r0得到余数 打印输出计数器和r3Assembly 试图在手臂上分开得到奇怪的结果,assembly,arm,Assembly,Arm,我正在尝试在不使用ARM组件中的divide函数的情况下进行除法。我的代码如下。由于某种原因,结果一直保持在2400年代 我已尝试将以下伪代码写入arm: 在r0和r1中获取输入 将r1添加到r3,直到r3超过r0 增量计数器 从r3中减去r0得到余数 打印输出计数器和r3 ldr r3,=0 ldr r6,=0 next: bl getnum mov r5,r0 bl getnum mov
ldr r3,=0
ldr r6,=0
next:
bl getnum
mov r5,r0
bl getnum
mov r6,r0
mov r0,r5
mov r1,r6
bl mydivide
b next
mydivide:
cmp r3,r0
bge rem
add r3,r3,r1
add r6,#1
b mydivide
rem:
sub r3,r0
mov r2,r3
mov r1,r6
ldr r0,=output
bl kprintf
output: .asciz"%dR%d\r\n"
预期:
? 100
? 40
2R20
实际:
? 100
? 40
40R2340使用调试器单步执行程序并查看出错的地方。显然,您使用了
r6
作为计数器,但从未对其进行初始化。您使用r6同时保存两个不同的值,一个计数器和一个除数。我记得ARM的快速但复杂的除法算法没有除法指令。他们使用了两个256字节的表,一个用于商数<256,另一个用于种子算法来查找1/商数(有时会偏离+1,因此必须进行最后一次乘法后检查)。@rcgldr:可能基于硬件ALU除法器使用的相同基数算法?除了最小的商,任何东西都比重复减法好。e、 有一个一次一位的O(logn)算法,使用移位。我认为这可能是基数-16或更高的基数HW div/sqrt单元所做的最简单的情况。对于常数除数,当然还有乘法逆(让编译器为您计算常数很方便)@PeterCordes-有一个商<256的检查,如果是,使用一个表。如果不是的话,那就是牛顿·拉斐逊的一个变种,即得到1/除数,它使每次迭代的位数翻倍,从另一个表中的7位开始。进行4次乘法和一些加法和移位,得到28位,然后用一个分子乘以除数,再进行一次乘法得到余数,并检查除法是否需要增加商。