我尝试使用输入四个浮点数scanf
,将它们存储到堆栈中,然后使用vmovupd
将它们复制到寄存器中以供使用。我的问题是,当我尝试输出这4个数字时,程序seg错误出现在printf
。
我认为它与堆栈有关,但是我尝试多次弹出(一次执行多个指令)无济于事。我还是汇编语言的新手,所以使用gdb
它对于我来说有点太先进了。
您会注意到我包含了一个名为的文件debug
。它使我能够查看寄存器和堆栈(这就是为什么要有dumpstack
指令的原因。)这是由我的教授提供的,它确实提供了一些帮助,但显然还不够(或者也许我只是缺少了一些东西)。
这是.cpp
:
#include <iostream>
using namespace std;
extern "C" double ComputeElectricity();
int main()
{
cout << "Welcome to electric circuit processing by Chris Tarazi." << endl;
double returnValue = ComputeElectricity();
cout << "The driver received this number: " << returnValue << endl;
return 0;
}
这是ASM
代码:
%include "debug.inc"
extern printf
extern scanf
global ComputeElectricity
;---------------------------------Declare variables-------------------------------------------
segment .data
greet db "This progam will help you analyze direct current circuits configured in parallel.", 10, 0
voltage db "Please enter the voltage of the entire circuit in volts: ", 0
first db "Enter the power consumption of device 1 (watts): ", 0
second db "Enter the power consumption of device 2 (watts): ", 0
third db "Enter the power consumption of device 3 (watts): ", 0
fourth db "Enter the power consumption of device 4 (watts): ", 0
thankyou db "Thank you. The computations have completed with the following results.", 10, 0
circuitV db "Curcuit total voltage: %1.18lf v", 10, 0
deviceNum db "Device number: 1 2 3 4", 10, 0
power db "Power (watts): %1.18lf %1.18lf %1.18lf %1.18lf", 10, 0
current db "Current (amps): %1.18lf %1.18lf %1.18lf %1.18lf", 10, 0
totalCurrent db "Total current in the circuit is %1.18lf amps.", 10, 0
totalPower db "Total power in the circuit is %1.18lf watts.", 10, 0
bye db "The analyzer program will now return total power to the driver.", 10, 0
string db "%s", 0
floatfmt db "%lf", 0
fourfloat db "%1.18lf %1.18lf %1.18lf %1.18lf", 0
;---------------------------------Begin segment of executable code------------------------------
segment .text
dumpstack 20, 10, 10
ComputeElectricity:
;dumpstack 30, 10, 10
;---------------------------------Output greet message------------------------------------------
mov qword rax, 0
mov rdi, string
mov rsi, greet
call printf
;---------------------------------Prompt for voltage--------------------------------------------
mov qword rax, 0
mov rdi, string
mov rsi, voltage
call printf
;---------------------------------Get voltage--------------------------------------------------
push qword 0
mov qword rax, 0
mov rdi, floatfmt
mov rsi, rsp
call scanf
vbroadcastsd ymm15, [rsp]
pop rax
;---------------------------------Prompt for watts 1--------------------------------------------
mov qword rax, 0
mov rdi, string
mov rsi, first
call printf
;---------------------------------Get watts 1---------------------------------------------------
push qword 0
mov qword rax, 0
mov rdi, floatfmt
mov rsi, rsp
call scanf
;---------------------------------Prompt for watts 2--------------------------------------------
mov qword rax, 0
mov rdi, string
mov rsi, second
call printf
;---------------------------------Get watts 2---------------------------------------------------
push qword 0
mov qword rax, 0
mov rdi, floatfmt
mov rsi, rsp
call scanf
;---------------------------------Prompt for watts 3--------------------------------------------
mov qword rax, 0
mov rdi, string
mov rsi, third
call printf
;---------------------------------Get watts 3---------------------------------------------------
push qword 0
mov qword rax, 0
mov rdi, floatfmt
mov rsi, rsp
call scanf
;---------------------------------Prompt for watts 4--------------------------------------------
mov qword rax, 0
mov rdi, string
mov rsi, fourth
call printf
;---------------------------------Get watts 4---------------------------------------------------
push qword 0
mov qword rax, 0
mov rdi, floatfmt
mov rsi, rsp
call scanf
;dumpstack 50, 10, 10
;---------------------------------Move data into correct registers------------------------------
vmovupd ymm14, [rsp] ; move all 4 numbers from the stack to ymm14
pop rax
pop rax
pop rax
pop rax
;dumpstack 55, 10, 10
vextractf128 xmm10, ymm14, 0 ; get lower half
vextractf128 xmm11, ymm14, 1 ; get upper half
;---------------------------------Move data into low xmm registers------------------------------
movsd xmm1, xmm11 ; move ymm[128-191] (3rd value) into xmm1
movhlps xmm0, xmm11 ; move from highest value from xmm11 to xmm0
movsd xmm3, xmm10
movhlps xmm2, xmm10
;showymmregisters 999
;---------------------------------Output results-------------------------------------------------
;dumpstack 60, 10, 10
mov rax, 4
mov rdi, fourfloat
push qword 0
call printf
pop rax
ret
问题在于您的堆栈使用情况。
首先,ABI docs指令rsp
必须 在 a 之前 对齐16个字节call
。
由于a call
会将8字节的返回地址压入堆栈,因此您需要将其rsp
乘以16加上8的倍数进行调整,以返回到16字节对齐。将16 * n + 8
被
包括 任何push
指令或其他更改RSP,而不仅仅是sub rsp, 24
。这是段错误的直接原因,因为printf
将使用对齐的SSE
指令,这将对未对齐的地址产生错误。
如果您解决了该问题,则堆栈仍然不平衡,因为您一直在推入值,但从不弹出它们。很难理解您想对堆栈做什么。
通常的方法是在函数的开头(序言)为本地人分配空间,并在函数的结尾(结尾)释放空间。如上所述,此数量(包括任何推送)应为16加8的倍数,因为函数 项
上的RSP (在调用方之后call
)距离16字节边界8字节。
在大多数glibc版本中,printf
当AL!= 0时,它只关心16字节的堆栈对齐。(因为这意味着有FP
args,因此它将所有XMM寄存器转储到堆栈中,以便可以为%f
转换建立索引。)
如果您使用未对齐的堆栈来调用它,即使它在您的系统上正常工作,这仍然是一个错误;将来的glibc版本 可能会 包含依赖16字节堆栈对齐的代码,即使没有FP
args也是如此。例如,scanf
即使AL=0
在大多数GNU / Linux发行版中,也确实在未对齐的堆栈上崩溃。
问题内容: 我用以下命令编译: 当我运行代码时,Linux抛出分段错误错误 (我正在使用Linux Mint Nadia 64位)。为什么会产生此错误? 问题答案: 因为是 不是 要退出的Linux,Windows或苹果机的程序的正确方法!!!! 不是函数,因为没有要返回的用户空间调用程序, 所以堆栈上没有返回地址 。用户空间中的执行在进程入口点从此处开始(在静态可执行文件中)。(或者使用动态链接
我在实现合并排序时遇到了分段错误。我已经检查了数组是否超出边界。我想得到一些帮助,找出我哪里出了问题。我尝试过小数组的输入,例如大小为10的数组,我将temp的大小作为静态值( 更新:我只需要改变mid=(低高)/2。
我们正在密集的测试负载中使用NIOFSDirectory而不是MMapDirectory进行索引。但是我们仍然得到一个带有mmapdirectory的SIGSEV。还有什么我要找的吗?这是一台Linux 64位计算机。堆栈跟踪的头部如下: 请让我知道什么更多的信息将是有帮助的。 谢谢... Java运行时环境检测到一个致命错误: SIGSEGV(0xB)(PC=0x00002AAAAB285EA7
我正在尝试使用 AWS PHP 开发工具包将一个 30 GB 的文件上传到亚马逊 S3。 它适用于最大7GB的文件。上传30 GB文件时,脚本运行约2小时后,我收到以下错误: 将部件上载到多部件上载时发生异常。以下部分出错:-第5部分:在上执行“UploadPart”时出错https://s3.amazonaws.com/Server3-27-SEP-2015/S3_www_1443369605.
当我使用真实凭据运行以下命令以获取标签时,我看到“分段错误” 以下是回溯: 这个问题是可重复的。file_sample是可构建的。我想这个问题可能与MS cppretsdk有关 同样的命令在Debian 10、MacOS 10.15.7上运行良好。 我有最新的 CentOS 7 和以下依赖关系 谢谢你, 阿列克谢
问题内容: 我正在从python开发C扩展,并且获得了一些段错误(在开发过程中不可避免…)。 我正在寻找一种显示段错误发生在哪一行代码的方法(一个想法就像跟踪每一行代码),我该怎么做? 问题答案: 这是一种输出代码运行的Python每行的文件名和行号的方法: 输出: (当然,您可能希望将跟踪输出写入文件。)