本文介绍了第二次使用MUL后出现分段故障的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我是汇编语言中的新手,我尝试创建函数并在C中使用它。这个函数得到3个变量a,x,y,它们是包含两个64位int的结构。我想返回a+x*y。不幸的是,这段代码是NASM导致段错误%define a1 [rdi]
%define a2 [rdi+8]
%define x1 [rsi]
%define x2 [rsi+8]
%define y1 [rdx]
%define y2 [rdx+8]
%define output1 rax
%define output2 rdx
%define res1 r8
%define res2 r9
global abc
abc:
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
使用第二个和第三个mul删除行允许我运行程序,而不会出现段错误。
推荐答案
如果您解开上面的宏定义,最终会产生这样的结果,这就是处理器实际尝试执行的内容:
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
或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
这篇关于第二次使用MUL后出现分段故障的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!