汇编乘法循环返回错误的高位数

时间:2016-09-23 00:42:53

标签: for-loop assembly x86 x86-64

我正在尝试编写一个for循环,通过将数字(var a)与另一个数字(var b)相加来进行乘法运算。

.globl times

times:
movl $0, %ecx        # i = 0

cmpl %ecx, %esi       #if b-i
jge end              # if >= 0, jump to end


 loop:
 addl (%edi, %eax), %eax  #sum += a
 incl %ecx               # i++
 cmpl %esi, %ecx         # compare (i-b)
 jl loop                 # < 0? loop b times total

 end:
 ret

我哪里错了?我已经完成了逻辑,我无法弄清问题是什么。

2 个答案:

答案 0 :(得分:3)

TL:DR:你没有将EAX归零,你的ADD指令正在使用内存操作数。

您应该使用调试器。您很容易就会发现EAX并非零开始。有关使用gdb调试asm的提示,请参阅标记wiki的底部。

我猜您使用的是x86-64 System V ABI,因此您的args(a和b)位于%edi和%esi。

在函数开始时,应该假定除了持有args的寄存器之外的寄存器包含垃圾。即使 持有你的args的寄存器的高位部分也可能包含垃圾。 (此规则例外:unofficially, narrow args are sign or zero extended to 32-bit by the caller

arg都不是指针,所以你不应该取消引用它们。 @IBAction func calculateButton(sender: AnyObject) { if patientWeight.text != "" && patientWeight.isNumber==true{ let weightPatient = Double(self.patientWeight.text!) self.dripAnswer.text = String(weightPatient! * 2) } else{ self.dripAnswer.text = "Please enter weight" } } 将32位地址计算为EDI + EAX,然后从那里加载32位。它将dword添加到EAX(目标操作数)。

我很震惊你的程序没有段错误,因为你使用整数arg作为指针。

对于许多x86指令(如ADD),目标操作数不是只写的。 add (%edi, %eax), %eax执行add %edi, %eax。我认为你正在混淆3操作数RISC语法,你可能会有EAX += EDI之类的指令。

x86有一些像这样的指令,作为最近的扩展添加,如BMI2 bzhi,但通常的指令都是具有破坏性目的地的2操作数。 (LEA除外,它不是从地址加载,而是将地址存储在目的地。所以add %src1, %src2, %dst可以工作。你甚至可以将结果放在不同的寄存器中。LEA is great for saving MOV instructions by doing shift+add and a mov all in one instruction, using the addressing mode syntax and machine-code encoding.

您的评论为lea (%edi, %eax), %eax。不知道你在那里谈论什么。 a是4个字节(不是位),并且你没有将(%edi)乘以任何东西。

只是为了好玩,这就是我编写功能的方式(如果我必须避免ie eax = sum + (a x 4bits) / imul %edi, %esi)。我假设两个args都是非负的,以保持简单。如果您的args是有符号整数,并且如果mov %esi, %eax为负数,则必须循环-b次,那么您需要一些额外的代码。

b

注意缩进样式,因此很容易找到分支目标。有些人喜欢在循环中缩进额外的指令。

你的方式运行正常(如果你做对了),但我的方式说明在asm中倒计时更容易(不需要额外的寄存器或立即保持上限)。此外,避免冗余比较。但是,在您熟悉编写至少有效的代码之前,不要担心优化。

答案 1 :(得分:1)

这是一个伪代码,记住这一点。

mov X,ebx <- put into EBX your counter, your B
mov Y,edx <- put into EDX your value, your A
mov 0,eax <- Result

loop:
add eax,edx
dec ebx
jnz loop <- While EBX is not zero

上述实现应该会使您的值进入EAX。您的代码看起来像是缺少eax初始化。