c – 分组

c – 分组,第1张

概述我试图用C语言定义一个基于 Linux命令的计算器dc,程序的结构并不那么重要,你需要知道我得到两个数字,我想在键入/时将它们分开.因此,我将这两个数字发送到进行除法的汇编函数(参见下面的代码).但这仅适用于正数. 当键入999 3 /它返回333这是正确的但是当键入-999 3 /我得到奇怪的数字1431655432并且当键入两个负数如-999 -3 /我每次得到0任何两个负数. 程序集中的代码 我试图用C语言定义一个基于 Linux命令的计算器dc,程序的结构并不那么重要,你需要知道我得到两个数字,我想在键入/时将它们分开.因此,我将这两个数字发送到进行除法的汇编函数(参见下面的代码).但这仅适用于正数.

当键入999 3 /它返回333这是正确的但是当键入-999 3 /我得到奇怪的数字1431655432并且当键入两个负数如-999 -3 /我每次得到0任何两个负数.

程序集中的代码是:

section .text global _div _div:   push rbp            ; Save caller state   mov rbp,rsp   mov rax,rdi        ; copy function args to registers: leftmost...   mov rbx,rsi        ; Next argument...   cqo  idiv rbx            ; divIDe 2 arguments   mov [rbp-8],rax   pop rbp             ; Restore caller state
解决方法 您的评论说您正在将整数传递给_idiv.如果你使用int那些是32位值:

extern int _div (int a,int b);

传递给函数时,a将位于RDI的底部32位,b将位于RSI的底部32位.参数的高32位可以是垃圾,但通常它们是零,but doesn’t have to be the case.

如果使用64位寄存器作为除数与IDIV,则除法为RDX:RAX / 64位除数(在您的情况下为RBX).这里的问题是您使用完整的64位寄存器进行32位除法.如果我们假设RDI和RSI的高位最初为0,那么RSI将为0x00000000FFFFFC19(RAX),RDI将为0x0000000000000003(RBX). CQO将RAX零扩展到RDX. RAX的最高位为零,因此RDX为零.该部门看起来像:

0x000000000000000000000000FFFFFC19 / 0x0000000000000003 = 0x55555408

0x55555408碰巧是1431655432(十进制),这是你看到的结果.一个解决方法是使用32位寄存器进行除法.要将EAX(RAX的低32位)扩展到EDX,您可以使用CDQ而不是CQO.然后您可以通过EBX划分EDX:EAX.这应该是你正在寻找的32位签名部门.代码看起来像:

cdqidiv ebx                 ; divIDe 2 arguments EDX:EAX by EBX

请注意,RBX,RBP,R12到R15都需要通过修改它们的功能来保存(它们是AMD 64-bit ABI中的易失性寄存器).如果您修改RBX,您需要确保像使用RBP一样保存和恢复它.更好的选择是使用一个易失性寄存器,如RCX而不是RBX.

您不需要中间寄存器来将除数放入.您可以直接使用RSI(或固定版本的ESI),而不是将其移动到RBX之类的寄存器.

总结

以上是内存溢出为你收集整理的c – 分组全部内容,希望文章能够帮你解决c – 分组所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1218650.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存