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

0

Я пытаюсь вывести результат пользователю после получения 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
    Почему бы не написать это на C ++ и просто заставить компилятор генерировать сборку? Затем со списком сборок сравните то, что вы делаете сейчас, с сгенерированным кодом сборки.
  • 0
    Разве вам не нужно высовывать этих толкаемых rbx, rcx ... перед 'ret'?
Показать ещё 3 комментария
Теги:
assembly
segmentation-fault
nasm

1 ответ

1

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

В вашем первом 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 .
  • 0
    Мой профессор назначил это как летнее задание, поэтому он бросил нас в огонь. Я не уверен, что такое стековый фрейм и как я его использовал. Я не дома в данный момент, но спасибо за публикацию, я дам вам знать, как идут дела, когда я вернусь домой.
  • 0
    Я исправил все остальное (больше нет ошибки сегмента), но я все еще не могу показать вывод?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню