Код NASM в Linux дает мне ошибку сегментации - PullRequest
0 голосов
/ 12 февраля 2011

Я начал изучать, как писать программы, используя язык программирования ассемблера NASM. Я написал эту простую программу, которая предлагает пользователю ввести два числа, а затем складывает два операнда вместе. Я получил его для компиляции без ошибок или предупреждений, но когда он запрашивает у пользователя два числа и начинает добавлять два числа, он выводит ошибку сегментации и программа завершается. Я знаю, что ошибка сегментации эквивалентна исключению нарушения прав чтения / записи в мире Win32. Но, потому что я не знаю, как отлаживать код NASM; Я не могу понять, что не так. Я подозреваю, что это связано с неверным указателем; но я не знаю Вот код ниже:

section .data 
    msg1: db 'Please Enter A Number: ', 0
    length1: equ $ - msg1
    msg2: db 'Please Enter A Second Number: ', 0
    length2: equ $ - msg2

section .bss
    operand1: resb 255
    operand2: resb 255
    answer: resb 255
section .text
    global _start

_start:

    ; Print first message

    mov eax, 4
    mov ebx, 1
    mov ecx, msg1
    mov edx, length1
    int 80h

    ; Now read value

    mov eax, 3
    mov ebx, 1
    mov ecx, operand1
    mov edx, 255
    int 80h

    ; Print second message

    mov eax, 4
    mov ebx, 1
    mov ecx, msg2
    mov edx, length2
    int 80h

    ; Now read second value

    mov eax, 3
    mov ebx, 1
    mov ecx, operand2
    mov edx, 255
    int 80h

    ; Now add operand1 and operand2 and print answer

    mov eax, 4
    mov ebx, 1
    xor ecx, ecx ; Make the ecx register 0
    mov ecx, operand1
    add ecx, operand2
    mov edx, 510
    int 80h

Ответы [ 2 ]

0 голосов
/ 13 февраля 2011

Значение в ecx - это адрес строки, которая должна быть напечатана при вызове int 80h. Последняя часть не имеет смысла

mov eax, 4
mov ebx, 1
xor ecx, ecx ; Make the ecx register 0
mov ecx, operand1
add ecx, operand2 ; **<<< invalid memory address now in ECX !!!**
mov edx, 510
int 80h

потому что вы добавляете адрес строкового операнда1 и адрес строкового операнда2 и пытаетесь напечатать все, что находится, и результирующий адрес, который, скорее всего, указывает в никуда.

Для отладки вашей программы с помощью gdb вы можете сделать:

nasm -f elf64 -g -l q1.lst q1.asm gcc -o q1 q1.o

Я заменил «_start» на «main», чтобы gcc не жаловался, и вы можете пропустить 64 в «-f elf64», если вы собираете 32-битную платформу.

GDB Q1

Вот пример сеанса GDB:

(gdb) br main Точка останова 1 в 0x4004d0: файл q1.asm, строка 20. (GDB) R Стартовая программа: / home / анонимный / проекты / asm / q1

Breakpoint 1, main () at q1.asm:20
20      mov eax, 4
(gdb) n
21      mov ebx, 1
(gdb) n
22      mov ecx, msg1
(gdb) n
23      mov edx, length1
(gdb) p msg1
$1 = 1634036816
(gdb) 
0 голосов
/ 12 февраля 2011

(Кроме того: вы должны читать с STDIN_FILENO = 0, а не STDOUT_FILENO = 1. Кроме того, вы пишете NUL символ, и вы не должны.)

Проблема в том, что operand1 и operand2 - это адреса в ячейках памяти, содержащих прочитанные вами символы. Когда вы добавляете их, вы получаете указатель на неверную память.

Вам придется преобразовать их в целые числа, добавить их и преобразовать обратно в строку, прежде чем вы сможете ее записать.

...