如果你解开上面的宏定义,你最终会得到这样的结果,这就是处理器实际上试图执行的:
mov rax, [rsi]
mul qword [rdx] <--- no segfault here
mov r8, rax
mov rax, [rsi]
mul qword [rdx+8] <--- segfault here
mov r9, rax
mov rax, [rsi+8]
mul qword [rdx] <--- segfault here
add r8, rax
mov rax, r8
mov rdx, r9
您说分段错误发生在上面标记的行上。
因此,让我们进行一些心灵调试(Raymond Chen 最喜欢的调试类型之一)。考虑第一次之后会发生什么mul
操作说明:rax
设置为产品的下部,并且rdx
设置为产品的高部分。
这意味着在第一次之后mul
, rdx
已经改变!它不再是一个指向y1
or to y2
,而是与 x1*y1 结果有关。在此之后的任何连续尝试都可以使用rdx
作为一个指针肯定会失败,因为它不再是一个指针了。
所以为了解决这个问题,你必须保留rdx
跨越另一个寄存器中的乘法。r10
此代码未使用它,并且它被认为是易失性的,因此我们可以安全地使用它来存储初始值的“备份”rdx
。所以这样的事情可能足以解决这个问题:
%define a1 [rdi]
%define a2 [rdi+8]
%define x1 [rsi]
%define x2 [rsi+8]
%define y1 [r10] ; Change which register we're using as the
%define y2 [r10+8] ; pointer to 'r10'.
%define output1 rax
%define output2 rdx
%define res1 r8
%define res2 r9
global abc
abc:
mov r10, rdx ; Preserve the real pointer to 'y1' in 'r10'.
mov output1, x1
mul qword y1
mov res1, output1
mov output1, x1
mul qword y2
mov res2, output1
mov output1, x2
mul qword y1
add res2, output1
mov output1, res1
mov output2, res2
ret