Ошибка сегментации в NASM 64bit

Я пытаюсь вывести результат пользователю после получения 3 входов от scanf,

Когда я запускаю свой код, я могу получить нужный мне ввод. Однако он вылетает после того, как я собрал данные и начал вычисление.

Кстати, я использую Ubuntu 14.04 с g ++ и NASM 64bit.

Вот как это должен смотреть:

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

0

Решение

Во-первых, с какой стати вы экономите ВСЕ из этих регистров?!? ABI для 64-битного Linux говорит, что вам нужно только сохранить rbx, rbp, а также r12 - r15 если вы используете эти регистры в своей функции. Кроме того, если вы используете Ассемблер, нет необходимости создавать стековый фрейм на 64-битной земле (плюс вы даже не используете rbp! так зачем создавать фрейм стека?) Единственное, что очень важно, это убедиться, что ваш стек выровнен по 16-байтовой границе — вызов отправляет 8-байтовый адрес возврата, так что все, что вам нужно в вашем ComputeArea функция sub rsp, 8 а также add rsp, 8 прямо перед тобой

В вашем первом scanf ты используешь rsp не настраивая его, вы просто что-то переписали!

Вы делаете некоторые вычисления здесь:

mov rax, 2
cvtsi2sd xmm3, rax

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

ret

Вы возвращаетесь из процедуры здесь, но не выталкиваете все те регистры, которые вы только что нажали !! Так что, в основном, ваш указатель стека испорчен! Процессор не знает, что такое обратный адрес!

То, что вы делаете в прологе, должно быть полностью изменено в эпилоге, прежде чем вы вернетесь!

Может быть, вы должны начать с простого, прочитать в 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 .
1

Другие решения


По вопросам рекламы [email protected]