C语言中的X86-64内联汇编(使用GCC编译),导致seg故障的多精度乘法例程
我试图在内联X86汇编中实现GMPC语言中的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,是因为这种方法通常会导致此特定设置的性
mpz\u t
对象的多精度乘法。根据我对输出变量约束的选择,我要么得到分段错误,要么输出变量中的值以不一致的方式损坏(即不同的代码运行导致值以不同的方式损坏)
此代码所做的是获取两个GMPmpz\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
约束选择了一个您执行过的寄存器,则它可能不正确。