我正在尝试将此C代码转换为Assembly,以便在不使用除法符号的情况下进行除法运算。C代码已经被证明是有效的。我已经尽我所能完成了C代码到汇编的转换。当除以1或分子中有0时,它将正确工作,但对于除法(如5789217 / 8、10 / 5等)将不工作。它们的输出总是商为0,余数为0。
我试着在这里和那里做一些小的调整,但最终我不确定汇编代码哪里出错了。
下面是C代码:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]){
//first command line argument is the dividend
long long dividend = atoll(argv[1]);
//second command line argument is the divisor
long long divisor = atoll(argv[2]);
//we need the remainder
long long remainder = 0;
//we need the quotient
long long quotient = 0;
if (divisor == 1) {
quotient = dividend;
remainder = 0;
} else {
//runs for 31 iterations as stated in the prompt
for(int i = 31; i >= 0; i--){
remainder <<= 1;
remainder |= (dividend >> i) & 1;
if (remainder >= divisor){
remainder -= divisor;
quotient |= 1 << i;
}
}
}
//print the results
printf("%lld / %lld = %lld R %lld\n", dividend, divisor, quotient, remainder);
return 0;
}
以下是更新的程序集代码:
.global _start
.data
dividend:
.long 100
divisor:
.long 100
quotient:
.long 0
remainder:
.long 0
.text
_start:
movl quotient, %eax
movl remainder, %edx
movl divisor, %esi # previously ecx
movl dividend, %ebx
movl $31, %ecx # previously esi
# first if statement that checks if the divisor is 1
cmpl $1, %esi
jne for_start
# divisor is 1, so quotient is dividend and remainder is 0
movl %ebx, %eax
xor %edx, %edx
jmp done
for_start:
cmpl $0, %ecx
jle done
# INSIDE FOR LOOP:
shll $1, %edx # shift remainder left
movl %ebx, %edi # copy dividend
shrl %cl, %edi # shift copy right
and $1, %edi # and 1 with the remainder
orl %edi, %edx # or the remainder and quotient CHECK THIS
# start of if statement
cmpl %esi, %edx # compare the remainder and the divisor
jle next_iter # if remainder is less than divisor, skip subtraction
sub %esi, %edx # subtract divisor from remainder
movl $1, %edi
shll %cl, %edi # Shift quotient left by cl
orl %edi, %eax # Or quotient with 1
next_iter:
decl %ecx # decrement loop counter
jns for_start
# END OF FOR LOOP
done:
nop
2条答案
按热度按时间4uqofj5v1#
示例汇编代码在this github gist中。(我是几个月前写的。我敢肯定,如果有人盯着我的算法足够长的时间,他们会找到一种方法把它撕成碎片。我终于有一个自己的工作了。
但你的算法完全不同。
你的算法的asm翻译的问题在这里:
在第一次循环之后,
%edx
是0或1。在第二次循环之后,它必须为0。它好像想读书
但这行不通,因为移位指令不存在。重做寄存器分配,使
i
位于%cl
中。(把除数放在%esi
或类似的地方。vngu2lb82#
我已经研究了一段时间了,但我相信这是答案。