我试图在从scanf获得3个输入后将结果输出给用户。
当我运行我的代码时,我能够得到我需要的输入。但是,在我收集输入并开始计算之后,它会崩溃。
顺便说一下,我用的是Ubuntu14.04和g++以及NASM64位。
应该是这样的:

This program is brought to you by Chris Tarazi

Welcome to Areas of Trapezoids

Please enter one of the base numbers: 5.8

Please enter the other base number: 2.2

Please enter the height: 6.5

****//Crashes here with Segmentation fault (core dumped)****

The area of a trapezoid with sizes 5.799999999999999365, 2.200000000000000153,
and 6.500000000000000000 is 26.000000000000000328

Have a nice day.  Enjoy your trapezoids.

C++文件:
#include <stdio.h>
#include <stdint.h>

extern "C" double ComputeArea();    // links with global in assembly

using namespace std;

int main()
{
    double area;

    printf("This program is brought to you by Chris Tarazi.\n");

    area = ComputeArea();

    printf("Have a nice day. Enjoy your trapezoids.\n");

    return 0;
}

程序集文件:
extern printf                                               ; This function will be linked later.

extern scanf

global ComputeArea                                          ; Declare function global to link with "extern" from C++.

;---------------------------------Declare variables-------------------------------------------
segment .data

welcome:                           db "Welcome to the area of trapezoids.", 10, 0

input:                             db "Please enter one of the base numbers: ", 0

secInput:                          db "Please enter the other base number: ", 0

output:                            db "The area of a trapezoid with sizes %1.18lf, %1.18lf, and %1.18lf is %1.18lf .", 10, 0

hInput:                            db "Please enter the height: ", 0

inputformat:                       db "%lf", 0

stringformat:                      db "%s", 0

fourfloatformat:                   db "%1.18lf  %1.18lf  %1.18lf  %1.18lf", 0


;---------------------------------Begin segment of executable code------------------------------
segment .text

ComputeArea:                                                    ; Area of trapezoid = ((a + b) / 2) * h.

    push       rbp                                              ; Save a copy of the stack base pointer
    mov        rbp, rsp                                         ; We do this in order to be 100% compatible with C and C++.
    push       rbx                                              ; Back up rbx
    push       rcx                                              ; Back up rcx
    push       rdx                                              ; Back up rdx
    push       rsi                                              ; Back up rsi
    push       rdi                                              ; Back up rdi
    push       r8                                               ; Back up r8
    push       r9                                               ; Back up r9
    push       r10                                              ; Back up r10
    push       r11                                              ; Back up r11
    push       r12                                              ; Back up r12
    push       r13                                              ; Back up r13
    push       r14                                              ; Back up r14
    push       r15                                              ; Back up r15
    pushf                                                       ; Back up rflags

;---------------------------------Output messages to user---------------------------------------
    mov qword rax, 0
    mov rdi, stringformat
    mov rsi, welcome
    call printf

    mov qword rax, 0
    mov rdi, stringformat
    mov rsi, input
    call printf

    push qword 0
    mov qword rax, 0
    mov rdi, inputformat
    mov rsi, rsp                ;firstbase
    call scanf
    movsd xmm0, [rsp]
    pop rax

    mov qword rax, 0
    mov rdi, stringformat
    mov rsi, secInput
    call printf

    push qword 0
    mov qword  rax, 0
    mov rdi, inputformat
    mov rsi, rsp                ;secondbase
    call scanf
    movsd xmm1, [rsp + 4]
    pop rax

    mov qword rax, 0
    mov rdi, stringformat
    mov rsi, hInput
    call printf

    push qword 0
    mov qword  rax, 0
    mov rdi, inputformat
    mov rsi, rsp                ;height
    call scanf
    movsd xmm2, [rsp + 8]
    pop rax

;---------------------------------Begin ComputeArea Calculation-----------------------------------

    mov rax, 2
    cvtsi2sd xmm3, rax

    addsd xmm0, xmm1
    divsd xmm0, xmm3
    mulsd xmm0, xmm2

    ret

;---------------------------------Output result to user-------------------------------------------
    mov rax, 3
    mov rdi, output
    call printf

最佳答案

首先,你到底为什么要保存所有这些记录?!? 64位Linux的ABI表示,如果在函数中使用这些寄存器,则只需保存rbxrbpr12 - r15。另外,使用汇编程序时,无需在64位land中创建堆栈帧(另外,您甚至不使用rbp!为什么要创建堆栈帧?)唯一非常重要的是确保堆栈在16字节的边界上对齐—调用会推送8字节的返回地址,因此ComputeArea函数中所需的只是在ret之前sub rsp, 8add rsp, 8
在你的第一个scanf中,你在使用rsp而没有调整它,你只是过度保护了一些东西!
你在这里做一些计算:

mov rax, 2
cvtsi2sd xmm3, rax

addsd xmm0, xmm1
divsd xmm0, xmm3
mulsd xmm0, xmm2

ret

你从这里的程序返回,但不要弹出所有你刚才推的寄存器!!所以基本上你的堆栈指针都是乱七八糟的!CPU不知道返回地址是什么!
你在开场白中所做的,在你回来之前必须在结尾部分颠倒过来!
也许,你应该从简单开始,读3个浮动,并尝试打印它们!
当我更正您的代码时,这是我的输出:
Welcome to the area of trapezoids.
Please enter one of the base numbers: 5.8
Please enter the other base number: 2.2
Please enter the height: 6.5
The area of a trapezoid with sizes 5.799999999999999822, 2.200000000000000178, and 6.500000000000000000 is 26.000000000000000000 .

关于c++ - NASM 64bit中的段错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25477787/

10-11 16:27