英文:
Converting this C Code to Assembly to do Division shifting one bit at a time
问题
以下是您提供的C代码和更新后的汇编代码的翻译部分:
C代码:
我正在尝试将此C代码转换为汇编,以执行除法而不使用除号。已经证明C代码有效。我已经尽力将C代码转换为汇编。当除数为1或分子为0时,它将正确工作,但对于诸如5789217 / 8,10 / 5等除法将不起作用。这些情况下的输出始终是商为0,余数为0。
我尝试了一些微小的调整,但最终不确定汇编代码的问题出在哪里。
以下是C代码:
// 包含标准输入输出库
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]){
// 第一个命令行参数是被除数
long long dividend = atoll(argv[1]);
// 第二个命令行参数是除数
long long divisor = atoll(argv[2]);
// 我们需要余数
long long remainder = 0;
// 我们需要商
long long quotient = 0;
if (divisor == 1) {
quotient = dividend;
remainder = 0;
} else {
// 根据提示,运行31次迭代
for(int i = 31; i >= 0; i--){
remainder <<= 1;
remainder |= (dividend >> i) & 1;
if (remainder >= divisor){
remainder -= divisor;
quotient |= 1 << i;
}
}
}
// 打印结果
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 # 之前是ecx
movl dividend, %ebx
movl $31, %ecx # 之前是esi
# 第一个if语句检查除数是否为1
cmpl $1, %esi
jne for_start
# 除数为1,所以商是被除数,余数为0
movl %ebx, %eax
xor %edx, %edx
jmp done
for_start:
cmpl $0, %ecx
jle done
# FOR循环内部:
shll $1, %edx # 左移余数
movl %ebx, %edi # 复制被除数
shrl %cl, %edi # 右移复制
and $1, %edi # 与余数做与运算
orl %edi, %edx # 或运算余数和商 CHECK THIS
# 开始if语句
cmpl %esi, %edx # 比较余数和除数
jle next_iter # 如果余数小于除数,则跳过减法
sub %esi, %edx # 从余数中减去除数
movl $1, %edi
shll %cl, %edi # 将商左移cl位
orl %edi, %eax # 或运算商和1
next_iter:
decl %ecx # 减小循环计数器
jns for_start
# FOR循环结束
done:
nop
英文:
I'm trying to convert this C Code to Assembly to do division without using the division sign. The C Code has been proven to work. I've finished converting the C Code to Assembly to the best of my ability. It will work correctly when dividing by 1 or when 0 is in the numerator, but will not work for division such as 5789217 / 8, 10 / 5, etc. The output for these is always that the quotient is 0 and the remainder is 0.
I tried making some minor tweaks here and there but ultimately im not sure where the assembly code is going wrong.
Here's the C Code:
#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;
}
Here is the UPDATED Assembly code:
.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
答案1
得分: 1
以下是翻译好的部分:
-
Example assembly code is in this github gist. (I had written it some months ago. Time to publish.) I'm certain if somebody stares at my algorithm long enough they'll find a way to tear it to shreds. I finally got one working on my own though.
-
Your algorithm is completely differently though.
-
The problem with your asm translation of your alrogithm is here:
shll $1, %edx # shift remainder left
shrl $1, %ebx # shift dividend right
and $1, %edx # and 1 with the remainder
-
After the first loop, %edx is either 0 or 1. After the second loop it must be 0.
-
It's like it wants to read
shll $1, %edx # shift remainder left
movl %ebx, %edi # copy dividend
shrl %esi, %edi # shift copy right
and $1, %edi # and 1 with the remainder
- but that doesn't work because that shift instruction doesn't exist. Redo register allocation so that i is in %cl instead. (Put the divisor in %esi or something like that.)
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
英文:
Example assembly code is in <A HREF="https://gist.github.com/joshudson/88570993c7863e4ba83af5fef61af2ad">this github gist</A>. (I had written it some months ago. Time to publish.) I'm certain if somebody stares at my algorithm long enough they'll find a way to tear it to shreds. I finally got one working on my own though.
Your algorithm is completely differently though.
The problem with your asm translation of your alrogithm is here:
shll $1, %edx # shift remainder left
shrl $1, %ebx # shift dividend right
and $1, %edx # and 1 with the remainder
After the first loop, %edx
is either 0 or 1. After the second loop it must be 0.
It's like it wants to read
shll $1, %edx # shift remainder left
movl %ebx, %edi # copy dividend
shrl %esi, %edi # shift copy right
and $1, %edi # and 1 with the remainder
but that doesn't work because that shift instruction doesn't exist. Redo register allocation so that i
is in %cl
instead. (Put the divisor in %esi
or something like that.)
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论