printf 上的分段错误 - NASM 64 位 Linux

2024-03-28

我尝试使用输入四个浮点数scanf,将它们存储到堆栈中,然后使用vmovupd将它们复制到寄存器以供使用。我的问题是,当我尝试输出这 4 个数字时,程序段错误位于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 code:

%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 文档要求rsp16 字节对齐before a call.

Since a call将把一个8字节的返回地址压入堆栈,你需要调整rsp16 的倍数加 8 以恢复 16 字节对齐。这16 * n + 8 is 包括 any pushRSP 的说明或其他更改,而不仅仅是sub rsp, 24。这是段错误的直接原因,因为printf将使用对齐SSE指令将因未对齐的地址而出错。

如果你解决这个问题,你的堆栈仍然不平衡,因为你不断推入值但从未弹出它们。很难理解你想用堆栈做什么。

通常的方法是在函数开头(序言)为局部变量分配空间,并在函数末尾(尾声)释放空间。如上所述,该金额(包括任何推送)应为 16 加 8 的倍数,因为 RSP 功能entry(在呼叫者之后call) 距 16 字节边界 8 字节。


在大多数 glibc 版本中,printf当 AL != 0 时,只会关心 16 字节堆栈对齐。(因为这意味着存在 FP 参数,因此它将所有 XMM 寄存器转储到堆栈,以便可以为它们建立索引%f转换。)

如果您使用未对齐的堆栈调用它,即使它恰好在您的系统上运行,它仍然是一个错误;未来的 glibc 版本could即使没有 FP 参数,也包含依赖于 16 字节堆栈对齐的代码。例如,scanf即使使用未对齐的堆栈,也已经崩溃了AL=0在大多数 GNU/Linux 发行版上。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

printf 上的分段错误 - NASM 64 位 Linux 的相关文章

  • 使用 systemctl 获取 systemd 进程的正常运行时间或停机时间?

    喜欢使用systemctl is active
  • GCC 从 C++ 程序生成的汇编代码中的 .cfi 和 .LFE 是什么?

    我有以下 C 代码 int factorial int n if n 0 return 1 return n factorial n 1 int main void factorial 5 return 0 当我使用 g S Factori
  • 如何从 Bash 命令行在后台 Vim 打开另一个文件?

    我正在从使用 Gvim 过渡到使用控制台 Vim 我在 Vim 中打开一个文件 然后暂停 Vim 在命令行上运行一些命令 然后想返回到 Vim Ctrl Z 在正常模式下 暂停 Vim 并返回到控制台 fg可用于将焦点返回到 Vim job
  • 尝试理解 printf() 的 gcc 汇编输出

    我正在尝试学习如何理解汇编代码 因此我一直在研究 GCC 的汇编输出以获取一些愚蠢的程序 其中之一只不过是int i 0 我现在或多或少完全理解了其中的代码 最大的困难是理解散布的 GAS 指令 无论如何 我向前迈了一步并添加了printf
  • 链接错误:命令行中缺少 DSO

    我对 Linux 使用 Ubuntu 14 04 LTS 64 位 相当陌生 来自 Windows 并且正在尝试移植我现有的 CUDA 项目 当通过链接时 usr local cuda bin nvcc arch compute 30 co
  • 如何在 Linux 和 C 中使用文件作为互斥体?

    我有不同的进程同时访问 Linux 中的命名管道 并且我想让此访问互斥 我知道可以使用放置在共享内存区域中的互斥体来实现这一点 但作为一种家庭作业 我有一些限制 于是 我想到的是对文件使用锁定原语来实现互斥 我做了一些尝试 但无法使其发挥作
  • BASH:输入期间按 Ctrl+C 会中断当前终端

    我的 Bash 版本是 GNU bash version 4 3 11 1 release x86 64 pc linux gnu 我有一段这样的代码 while true do echo n Set password read s pas
  • “git add”返回“致命:外部存储库”错误

    我刚刚进入 git 的奇妙世界 我必须提交我对程序所做的一系列更改 位于名为的目录中 var www myapp 我创建了一个新目录 home mylogin gitclone 从这个目录中 我做了一个git clone针对公共回购 我能够
  • 内存映射图形输出

    我正在探索使用内存映射图形绘制像素和线条 我在 Windows 的 Textpad 中使用 TASM 当我单击 运行 时 整个屏幕变成蓝色 就是这样 没有绘制像素 model small stack data saveMode db xVa
  • Ubuntu Python shebang 线不工作

    无法让 shebang 线在 Ubuntu 中为 python 脚本工作 我每次只收到命令未找到错误 test py usr bin env python print Ran which python usr bin python 在 sh
  • Python 3.4.3 subprocess.Popen 在没有管道的情况下获取命令的输出?

    我试图将命令的输出分配给变量 而不让命令认为它正在通过管道传输 原因是 如果正在通过管道传输 则相关命令会给出未格式化的文本作为输出 但如果从终端运行 则会给出颜色格式化的文本 我需要获取这种颜色格式的文本 到目前为止我已经尝试了一些事情
  • 查找用户输入中的第一个和最后一个大写字母

    输入将从 a z 或 A Z 中获取 并且输入以星号结束 我们需要将输入字符的第一个和最后一个大写字母作为输出 另外 我们应该显示每次输入的内容 注意 我们逐个字符地获取输入 而不是作为字符串 测试用例1 输入 aAbCcP 输出 AP 测
  • 在汇编中,指令指定数据类型吗?

    我是汇编语言编程 x86 的初学者 以下说法是否正确 在汇编中 BYTE WORD DWORD 等数据类型分别表示 8 位 16 位和 32 位模式 而不仅仅是整数 它们本身没有意义 它们只是位模式 使用它们的指令赋予了它们意义 汇编 代码
  • ioctl 命令的用户权限检查

    我正在实现 char 驱动程序 Linux 并且我的驱动程序中有某些 IOCTL 命令仅需要由 ADMIN 执行 我的问题是如何在 ioctl 命令实现下检查用户权限并限制非特权用户访问 IOCTL 您可以使用bool capable in
  • 找不到包“gdk-pixbuf-2.0”

    我正在尝试在 Amazon Linux 发行版实例上构建 librsvg 我已经通过 yum 安装了大部分依赖项 其中一些在实例上启用的默认 yum 存储库中不可用 因此必须从头开始构建它们 我已经走了很远 但还停留在最后一点 跑步时sud
  • 仅使用containerd(不使用Docker)修剪容器镜像

    如果我刚刚containerd安装在 Linux 系统上 即 Docker 是not安装 如何删除未使用的容器映像以节省磁盘空间 Docker 就是这么方便docker system prune https docs docker com
  • Linux 中 m 标志和 o 标志将存储在哪里

    我想知道最近收到的路由器通告的 m 标志和 o 标志的值 从内核源代码中我知道存储了 m 标志和 o 标志 Remember the managed otherconf flags from most recently received R
  • 有没有一种快速方法可以从 Jar/war 中删除文件,而无需提取 jar 并重新创建它?

    所以我需要从 jar war 文件中删除一个文件 我希望有类似 jar d myjar jar file I donot need txt 的内容 但现在我能看到从 Linux 命令行执行此操作的唯一方法 不使用 WinRAR Winzip
  • 我们真的应该使用 Chef 来管理 sudoers 文件吗?

    这是我的问题 我担心如果 Chef 破坏了 sudoers 文件中的某些内容 可能是 Chef 用户错误地使用了说明书 那么服务器将完全无法访问 我讨厌我们完全失去客户的生产服务器 因为我们弄乱了 sudoers 文件并且无法再通过 ssh
  • python获取上传/下载速度

    我想在我的计算机上监控上传和下载速度 一个名为 conky 的程序已经在 conky conf 中执行了以下操作 Connection quality alignr wireless link qual perc wlan0 downspe

随机推荐

  • BeautifulSoup 在按复合类名搜索时返回空列表

    使用正则表达式按复合类名搜索时 BeautifulSoup 返回空列表 Example import re from bs4 import BeautifulSoup bs a class name single name692 href
  • 编写 Prolog 谓词的最佳实践是什么,以便它以指定参数的不同方式工作

    我正在尝试实现一些简单的谓词 例如 my length 或 my append 如果我们事先知道我们想要找到列表的长度 或者我们想要附加两个列表 这对我来说很容易 即我知道什么是输入 什么是输出 在 Prolog 中 可以用其他方式做事 如
  • Selenium findElements() 多次返回第一个元素的同一实例

    我需要获取所有文章标题的列表 但由于某种原因 Selenium 返回了文章 WebElement 的同一实例 3 次 网页 HTML 如下所示 div class site content clearfix div class contai
  • 如何使用 uibinder 创建带有子级的 gwt 复合组件?

    我想创建一个组件来装饰它的子组件 例如 mycomponent ui xml
  • formData.has() 不是一个函数[重复]

    这个问题在这里已经有答案了 我正在尝试执行简单的 ajax 文件上传 但收到 未捕获的类型错误 formData has 不是函数 如果我还注释掉 formData has 检查函数并将其替换为 formData append myResu
  • MS Azure Web 角色 - 如何指定 Webroot 驱动器存储大小

    我正在开发一个非常大且复杂的企业 Web 应用程序 托管在 azure 中 注意到 Web 根目录位于 E 盘 我还注意到 C 驱动器的大小为 490GB 但有趣的是 E盘上的Web根目录大小只有1GB 有什么方法可以指定您要安装的驱动器
  • 如何保护此代码免遭 SQL 注入?有点困惑

    我已经阅读了各种来源 但我不确定如何将它们实现到我的代码中 我想知道是否有人可以帮我快速完成它 一旦我在代码中被展示如何做到这一点 我想我就能学会它 这是来自我在网上找到的 AJAX 自动完成 尽管我看到它由于 queryString 或其
  • 使用php将图像保存到服务器

    嘿 我有以下脚本 基本上是一个闪存文件向它发送一些数据 它创建一个图像 然后为用户打开一个另存为对话框 以便他们可以将图像保存到系统中 问题来了 如何我还要将图像保存到我的服务器吗
  • Laravel - 多对多多态关系

    我正在努力反对 Laravel 5 7 中的多态关系定义 数据情况如下 我有一个用户模型 一个产品模型和一个销售模型 我基本上想为我的用户构建一个愿望清单 它可以包含商品和产品 并且我希望在那里有一个多态关系 因为我将不得不添加新类型的东西
  • AWS S3 中有乐观锁吗?

    我在 s3 中有一个 excel 文件 由于不同的程序读取和写入它 我需要保证每个程序都写入它们读取的版本 S3仅保证新创建对象的读后一致性 以及覆盖和删除对象的最终一致性 如果您的 Excel 文件足够小 小于 400kb 您可以将其存储
  • TYPO3 表单多复选框部分

    我尝试编辑核心文件 form Resources Private Frontend Partials Field Field html 以更改前端中的 html 输出 如果我更改该文件 它不会产生任何影响 如果我更改核心文件 form Re
  • 同时显示两个片段

    From FragmentPagerAdapter in case 0我实例化了fragment A我想显示的这个片段显示里面的两个片段frag A 视图未显示 我的 FragmentPagerAdapter 由主类调用来填充 viewpa
  • 如何使用 VS 2008 和 IE 完全禁用 JavaScript 错误

    我试图防止 VS 因 JS 错误而中断 我有以下设置 在 IE 下 Tools gt Internet Settings gt Advanced tab gt Browsing Disable script debugging Intern
  • Jquery Ajax CORS + HttpOnly Cookie

    我已经在我当前的项目中使用了 CORS 尽管我似乎无法正常工作的一件事是 cookie 现在我得到了 cookie 服务器发出它并将其发送下来 firefox 接受它 我可以在 firebug cookies 部分看到它 然而 当我对该服务
  • 如何使用 Swashbuckle.AspNetCore 将自定义泛型类型公开为 Swagger 架构中的字符串

    我有一个自定义泛型类型 大致如下所示 public struct Foo
  • Scrapy:如何在蜘蛛中使用项目以及如何将项目发送到管道?

    我是新来的scrapy我的任务很简单 对于给定的电子商务网站 抓取所有网站页面 寻找产品页面 如果 URL 指向产品页面 创建一个项目 处理项目以将其存储在数据库中 我创建了蜘蛛 但产品只是打印在一个简单的文件中 我的问题是关于项目结构 如
  • 连接两个具有交替值的数组

    连接两个具有交替值的数组的最佳方法是什么 比方说array1 is 1 3 5 7 array2 is 2 4 6 8 我想将这两个数组组合起来 结果是 1 2 3 4 5 6 7 8 In Java int a1 1 3 5 7 int
  • ajax jquery 总是运行错误

    每次我运行我的 ajax jquery 函数时 我都会收到一个错误 这适用于我所有的 ajax 调用 这是我的代码的示例 function FindContact CompanyName DivisionName FirstName Las
  • 如何使用 Python 制作时间表的图像/PDF

    我正在解决时间表安排问题 并希望以 PDF 或图像集的形式打印最终输出 我有多个部分 每个部分都有自己的时间表 我为每个部分创建了一个二维数组 该数组的大小为 5 x 5 5 天 每天有 5 个时段 数组的每个索引代表一个讲座时段 现在 这
  • printf 上的分段错误 - NASM 64 位 Linux

    我尝试使用输入四个浮点数scanf 将它们存储到堆栈中 然后使用vmovupd将它们复制到寄存器以供使用 我的问题是 当我尝试输出这 4 个数字时 程序段错误位于printf 我认为这是堆栈的问题 但我尝试多次弹出 一次多条指令 但无济于事