C语言中的X86-64内联汇编(使用GCC编译),导致seg故障的多精度乘法例程

C语言中的X86-64内联汇编(使用GCC编译),导致seg故障的多精度乘法例程,c,gcc,assembly,x86,gmp,C,Gcc,Assembly,X86,Gmp,我试图在内联X86汇编中实现GMPmpz\u t对象的多精度乘法。根据我对输出变量约束的选择,我要么得到分段错误,要么输出变量中的值以不一致的方式损坏(即不同的代码运行导致值以不同的方式损坏) 此代码所做的是获取两个GMPmpz\U t对象,ain和bin,每个对象都保证大小为13(即\u mp\U size设置为13,对象由13个64位数字定义),然后生成大小为26的mpz\U t对象,res,这是将ain和bin相乘的结果。我之所以不使用mpz_mul,是因为这种方法通常会导致此特定设置的性

我试图在内联X86汇编中实现GMP
mpz\u t
对象的多精度乘法。根据我对输出变量约束的选择,我要么得到分段错误,要么输出变量中的值以不一致的方式损坏(即不同的代码运行导致值以不同的方式损坏)

此代码所做的是获取两个GMP
mpz\U t
对象,
ain
bin
,每个对象都保证大小为13(即
\u mp\U size
设置为13,对象由13个64位数字定义),然后生成大小为26的
mpz\U t
对象,res,这是将
ain
bin
相乘的结果。我之所以不使用
mpz_mul
,是因为这种方法通常会导致此特定设置的性能提高

请注意,
res->\ump\ud、ain->\ump\ud
bin->\ump\ud
是指定义各自
mpz\ut
对象的“肢体”数组,其中
(obj->\ump\ud)[0]
是最低有效肢体,而
(obj->\ump\ud obj->\ump\u size-1]
是最有效肢体

如果有人能帮我解释一下我做错了什么,我会非常感激的!下面是一段代码。我排除了大会的大部分内容,因为它是重复性的,但我认为我给出的足以很好地说明正在发生的事情:

void mpz_mul_x86_1(mpz_t res, mpz_t ain, mpz_t bin){

   if( res->_mp_alloc<26) //the next few lines makes sure res is large enough
     _mpz_realloc(res,26); //the result of the multiplication

   res->_mp_size = 26;


   asm volatile (            
     "movq 0(%1), %%rax;" 
     "mulq 0(%2);"
     "movq %%rax, 0(%0);"    
     "movq %%rdx, %%r8;"           //A0*B0
                                   //0

     "xorq %%r10, %%r10;" 

     "movq 8(%1), %%rax;"      
     "mulq 0(%2);"              
     "addq %%rax, %%r8;"     
     "movq %%rdx, %%r9;"  
     "adcq $0, %%r9;"              //A1*B0

     "movq 0(%1), %%rax;"  
     "mulq 8(%2);"         
     "addq %%rax, %%r8;" 
     "movq %%r8, 8(%0);"  
     "adcq %%rdx,%%r9;"    
     "adcq $0, %%r10;"                //A0*B1
                                     //1

     "xorq %%r8, %%r8;" 

     "movq 0(%1), %%rax;"
     "mulq 16(%2);"            
     "addq %%rax, %%r9;"            
     "adcq %%rdx, %%r10;"
     "adcq $0, %%r8;"           //A0*B2

     "movq 8(%1), %%rax;"
     "mulq 8(%2);"            
     "addq %%rax, %%r9;"            
     "adcq %%rdx, %%r10;"
     "adcq $0, %%r8;"        //A1*B1

     "movq 16(%1), %%rax;"
     "mulq 0(%2);"            
     "addq %%rax, %%r9;"    
     "movq %%r9, 16(%0);" 
     "adcq %%rdx, %%r10;"
     "adcq $0, %%r8;"            //A2*B0
                                 //2
     "xorq %%r9, %%r9;"  

     "movq 24(%1), %%rax;"
     "mulq 0(%2);"            
     "addq %%rax, %%r10;"            
     "adcq %%rdx, %%r8;"
     "adcq $0, %%r9;"              //A3*B0

     "movq 0(%1), %%rax;"
     "mulq 24(%2);"            
     "addq %%rax, %%r10;"            
     "adcq %%rdx, %%r8;"
     "adcq $0, %%r9;"            //A0*B3

     "movq 16(%1), %%rax;"
     "mulq 8(%2);"            
     "addq %%rax, %%r10;"            
     "adcq %%rdx, %%r8;"
     "adcq $0, %%r9;"        //A2*B1

     "movq 8(%1), %%rax;"
     "mulq 16(%2);"            
     "addq %%rax, %%r10;"   
     "movq %%r10, 24(%0);" 
     "adcq %%rdx, %%r8;"
     "adcq $0, %%r9;"        //A1*B2
                             //3


    /*About 1000 lines of omitted Assembly code is from here*/


     "xor %%r8, %%r8;"

     "movq 96(%1), %%rax;"
     "mulq 88(%2);"            
     "addq %%rax, %%r9;"
     "adcq %%rdx, %%r10;"
     "adcq $0, %%r8;"    //A12*B11

     "movq 88(%1), %%rax;"
     "mulq 96(%2);"            
     "addq %%rax, %%r9;"
     "movq %%r9, 184(%0);"
     "adcq %%rdx, %%r10;"
     "adcq $0, %%r8;"    //A11*B12
                         //23
     "xor %%r9, %%r9;"

     "movq 96(%1), %%rax;"
     "mulq 96(%2);"            
     "addq %%rax, %%r10;"
     "movq %%r10, 192(%0);"
     "adcq %%rdx, %%r8;"
     "adcq $0, %%r8;"    //A12*B12
                         //24

     "movq %%r8, 200(%0);" //25


     :  "=&r" (res->_mp_d) 
     : "r" ((ain->_mp_d)), "r" ((bin->_mp_d))
     : "%rax", "%rdx", "%r8", "%r9", "%r10", "memory", "cc"
     );
}
void mpz_mul_x86_1(mpz_t res,mpz_t ain,mpz_t bin){
如果(res->mp\u alloc\u mp\u size=26;
挥发性物质(
movq 0(%1),%%rax
“mulq 0(%2);”
“movq%%rax,0(%0);”
“movq%%rdx,%%r8;”//A0*B0
//0
xorq%%r10,%%r10
movq 8(%1),%%rax
“mulq 0(%2);”
addq%%rax,%%r8
“movq%%rdx,%%r9;”
“adcq$0,%%r9;”//A1*B0
movq 0(%1),%%rax
“mulq 8(%2);”
addq%%rax,%%r8
“movq%%r8,8(%0);”
“adcq%%rdx,%%r9;”
“adcq$0,%%r10;”//A0*B1
//1
xorq%%r8,%%r8
movq 0(%1),%%rax
“mulq 16(%2);”
addq%%rax,%%r9
“adcq%%rdx,%%r10;”
“adcq$0,%%r8;”//A0*B2
movq 8(%1),%%rax
“mulq 8(%2);”
addq%%rax,%%r9
“adcq%%rdx,%%r10;”
“adcq$0,%%r8;”//A1*B1
movq 16(%1),%%rax
“mulq 0(%2);”
addq%%rax,%%r9
“movq%%r9,16(%0);”
“adcq%%rdx,%%r10;”
“adcq$0,%%r8;”//A2*B0
//2
xorq%%r9,%%r9
movq 24(%1),%%rax
“mulq 0(%2);”
addq%%rax,%%r10
“adcq%%rdx,%%r8;”
“adcq$0,%%r9;”//A3*B0
movq 0(%1),%%rax
“mulq 24(%2);”
addq%%rax,%%r10
“adcq%%rdx,%%r8;”
“adcq$0,%%r9;”//A0*B3
movq 16(%1),%%rax
“mulq 8(%2);”
addq%%rax,%%r10
“adcq%%rdx,%%r8;”
“adcq$0,%%r9;”//A2*B1
movq 8(%1),%%rax
“mulq 16(%2);”
addq%%rax,%%r10
“movq%%r10,24(%0);”
“adcq%%rdx,%%r8;”
“adcq$0,%%r9;”//A1*B2
//3
/*这里大约有1000行省略的汇编代码*/
异或%%r8,%%r8
movq 96(%1),%%rax
“mulq 88(%2);”
addq%%rax,%%r9
“adcq%%rdx,%%r10;”
“adcq$0,%%r8;”//A12*B11
movq 88(%1),%%rax
“mulq 96(%2);”
addq%%rax,%%r9
movq%%R9184(%0)
“adcq%%rdx,%%r10;”
“adcq$0,%%r8;”//A11*B12
//23
异或%%r9,%%r9
movq 96(%1),%%rax
“mulq 96(%2);”
addq%%rax,%%r10
“movq%%R10192(%0);”
“adcq%%rdx,%%r8;”
“adcq$0,%%r8;”//A12*B12
//24
“movq%%r8200(%0);”//25
:“=&r”(res->\U mp\d)
:“r”((ain->ump\ud)),“r”((bin->ump\ud))
:%rax、%rdx、%r8、%r9、%r10、内存、抄送
);
}

您错误地声明res->\u mp\u d是asm语句的一个输出,而实际上它是一个指向输出的指针的输入。

太多的内联程序集。将其用于基本要素,其余部分用C完成。这种展开级别实际上对x86-64微体系结构有害,就像“Comba”(按列)一样乘法运算。@BrettHale-谢谢Brett。这些东西到底有什么害处?最好有一个适合缓存线的快速行“mul-add”循环,具有高度可预测的分支。行数据也是如此。以及Intel/AMD手册,都是一个很好的资源。@Dieter-您可能想要反汇编对象文件并确保按预期替换了
%0
%1
%2
。如果
r
约束选择了一个您执行过的寄存器,则它可能不正确。