回 帖 发 新 帖 刷新版面

主题:求助, 加法进位的问题

我写了个128位的加法函数,但不知道错在哪里:
   0xfffffffd 00000000 00000000 fffffffe
+  0x00000000 00000001 00000002 00000003
=  0xfffffffd 00000001 00000003 00000001
这个加法应该是没有溢出的。 我写的add128这个函数可以算出正确的结果,但是返回的状态是溢出了(返回0是没溢出,1是溢出),不知道哪里错了。哪位大牛帮我分析下,谢谢。
[code=c]
/*
  Dev-C++ 4.9.9.2
*/

#include <stdio.h>

#define PRINT(x)  printf("\n%-7s",#x)
#define check(x)  PRINT(x),_check(&x)


typedef struct int128{
  unsigned int _0, _1, _2, _3;        
}int128;


/*  
  这个函数计算 128位数的加法: *p = n1 + n2
*/
inline int 
add128 (int128 *p, int128 n1, int128 n2)
{
__asm__ ( "movl %0, %%edx\n\n\t" : :"p"(p) );//把p的值存如edx 
__asm__ ( "movl %0, %%eax  \n\t"
          "addl %1, %%eax\n\t"
          "movl %%eax,(%%edx)\n"
          :
          :"m"(n1._0), "m"(n2._0)
        );//p->_0 = n2._0+n1._0;最低位相加,加法指令用add 
__asm__ ( "movl %0, %%eax  \n\t"
          "adcl %1, %%eax  \n\t"
          "movl %%eax,4(%%edx)\n"
          :
          :"m"(n1._1), "m"(n2._1)
        );//p->_1 = n2._1+n1._1;不过加法指令用adc 
__asm__ ( "movl %0, %%eax  \n\t"
          "adcl %1, %%eax  \n\t"
          "movl %%eax,8(%%edx)\n"
          :
          :"m"(n1._2), "m"(n2._2)
        );//p->_2 = n2._2+n1._2;不过加法指令用adc 
__asm__ ( "movl %0, %%eax  \n\t"
          "adcl %1, %%eax  \n\t"
          "movl %%eax,12(%%edx)\n"
          :
          :"m"(n1._3), "m"(n2._3)
        );//p->_3 = n2._3+n1._3;不过加法指令用adc  
__asm__ ( "lahf \n\t"
          "andl $0x1, %eax \n\t"
        );//把FLAG的状态传入ah,然后让eax和0x1 做&运算,提取CF的状态
          //如果CF为1,这此次加法 溢出 
}


/*
  把指针p指向的对象(128位整数) 按照高位到低位的顺序输出
*/
void _check( const int128 *p)
{
printf(" 0X %08x %08x %08x %08x ",(*p)._3,(*p)._2,(*p)._1,(*p)._0);
}


/****************  主函数  *****************/
int main(void)
{
int128 n1 = {0xfffffffeUL,0,0,0xfffffffdUL};
int128 n2 = {3,2,1,0}, n3={0};

int status = add128(&n3,n1,n2);// n1 + n2的值保存到 n3,status记录是否溢出

printf("\n%*s",35,"高位   <--   低位"); 
check(n1);check(n2);check(n3);
printf("\nstatus= %d\n",status);

puts("\nexit\n");
return 0;
}[/code]

回复列表 (共2个回复)

沙发

说实话,这个我看不懂,不好意思。

板凳

不过还是谢谢楼上的 ,代码的问题我已经找到了。其实错误原因很简单:

__asm__ ( "lahf \n\t"
          "andl $0x1, %eax \n\t"
        );//把FLAG的状态传入ah,然后让eax和0x1 做&运算,提取CF的状态
          //如果CF为1,这此次加法 溢出 
应该改为:
__asm__ ( "lahf \n\t"
          "andl $0x100, %eax \n\t"
        );//如果溢出返回0x100,没有溢出返回0

lahf是把标志寄存器的值复制到ah寄存器中,并不是al中,所以要提取CF的状态要用0x100来和eax做&运算。

是我对汇编指令不是很熟悉才会出现这样的错误,对gcc内联汇编也有很多技巧了解的也不多。

最近我在写128位(无符号)整数的代码,等完成我把源代码贴出来。现在加减乘除和位运算初步完成了。还剩下输入输出部分没完成。在实现输出部分的时候又遇到了一些问题:
printf函数的格式部分可以总结为:
    %[flags][width][.precision][|l|L|h][type]

问题1. [|l|L|h]这一部分有什么用,在网上也没查到比较详细的解释。
问题2. [type]为n的时候是什么意思,比如 printf("%c%n%d",'a',pi,i);这句话的pi那部分是什么意思。
问题3. [type]为e,g,f我没能想到比较好的实现方法。

我来回复

您尚未登录,请登录后再回复。点此登录或注册