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

ctzdev

我尝试使用输入四个浮点数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文档任务rsp是对准16字节的一个call

由于acall会将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发行版中也确实在未对齐的堆栈上崩溃

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

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

来自分类Dev

Segmentation fault on printf - NASM 64bit Linux

来自分类Dev

nasm 64,分段错误

来自分类Dev

在redHat linux RHEL 6.2 64bit机器上安装zmq模块

来自分类Dev

在redHat linux RHEL 6.2 64bit机器上安装zmq模块

来自分类Dev

如何使用mingw在Linux上链接64bit dll文件

来自分类Dev

_start中RET上的nasm分段错误

来自分类Dev

尝试在Linux Mint 17.1 64bit上“制作” C ++项目时,来自cstdlib的错误以及类似的错误(未声明/不是类型)

来自分类Dev

NASM printf打印64位双段错误

来自分类Dev

NASM Linux共享对象错误:针对'.data'重定位R_X86_64_32S

来自分类Dev

卸载utorrent,在32bit上安装64bit

来自分类Dev

安装的字体未显示,Linux Mint 15 64bit

来自分类Dev

如何在Windows上构建gettext 64bit dll。

来自分类Dev

Windows 8 64bit上的FileZilla 3.7.2

来自分类Dev

在Windows 7 64bit上更新ASUS BIOS

来自分类Dev

在Windows 7上构建vim 64bit

来自分类Dev

在Ubuntu 14.10(64bit)上的LispWorks PE(安装)

来自分类Dev

无法在Windows 7 / 64bit上启动Express App

来自分类Dev

Cygwin / Windows 64bit上的堆栈大小是多少?

来自分类Dev

在Ubuntu 64bit 15.10上运行Steam?

来自分类Dev

无法让Steam在Ubuntu 14.04 64bit上启动

来自分类Dev

64位NASM中的Linux sys_open返回负值

来自分类Dev

Linux x86_64 nasm汇编系统调用

来自分类Dev

Linux上的AVX分段错误

来自分类Dev

为什么mov rax,cr0会导致nasm 64位中的分段错误

来自分类Dev

在NASM Linux中拍摄

来自分类Dev

Linux上的NASM Hello World:对“ main”的未定义引用

来自分类Dev

如何在Linux上的NASM中创建UEFI内核

来自分类Dev

Linux上的NASM Hello World:对“ main”的未定义引用

Related 相关文章

热门标签

归档