NASM - ошибка сегментации и другие проблемы - PullRequest
1 голос
/ 16 февраля 2012

это мой первый пост здесь. Я не уверен, правильно ли я выполнил форматирование, поэтому прости меня, если я все испортил.

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

[poise] [/home/a/a_mccr/terminal] > ./assignment2
Please enter a four-digit number, negative or positive
1234
The number you entered is
Half the entered value is
ÞH
Double the entered value is
x#      ÞH
Segmentation fault

Он не распечатывает мой ввод (то есть 1234), а затем каждый раз, когда выводом является PH, а затем X # PH. Все это указывает на то, что ввод не сохраняется, но я не могу понять, почему. Также я получаю загадочную ошибку сегментации в конце моей программы ... Помогите! Вот код:

segment .data                   ;to compile use:        nasm -f elf assignment2.asm
                            ;                       ld -o assignment2 assignment2.o

    msg1 db 'Please enter a four-digit number, negative or positive', 0xA
    len1 equ $-msg1         ;length of 1st message
    msg2 db 'The number you entered is', 0xA
    len2 equ $-msg2         ;length of 2nd message
    msg3 db 'Half the entered value is', 0xA
    len3 equ $-msg3         ;length of 3rd message
    msg4 db 'Double the entered value is', 0xA
    len4 equ $-msg4         ;length of 4th message

segment .bss

    input2 resb 3           ;reserve 5 bytes for the entered number
    input resb 3            ;reserve 5 bytes for the entered number

segment .text
    global _start

_start:
    mov eax, 4      ;select kernel call 4, the write function
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, msg1   ;set the pointer to msg
    mov edx, len1   ;set the length to len
    int 0x80        ;call write function

    mov eax, 3      ;select the kernel read function
    mov ebx, 0      ;use the default input device (user txt input)
    mov ecx, input  ;pointer to input variable
    int 0x80        ;invoke kernel read function

    mov eax, 4      ;select kernel call 4, the write function
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, msg2   ;set the pointer to msg2
    mov edx, len2   ;set the length to len2
    int 0x80        ;call write function

    mov eax, 4      ;select kernel call 4, the write function
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, input  ;set the pointer to input
    int 0x80        ;call write function

    mov eax, [input]        ;move input to eax register
    mov ebx, [input]        ;move input to ebx register

    shr eax, 1      ;shift eax 1 place to the right
    shl ebx, 1      ;shift ebx 1 place to the left

    mov [input], eax        ;move contents of eax to input
    mov [input2], ebx       ;move contents of ebx to input2

    mov eax, 4      ;Write message about half
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, msg3   ;set the pointer to msg3
    mov edx, len3   ;set the length to len3
    int 0x80        ;call write function

    mov eax, 4      ;write contents of input
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, input  ;set the pointer to input
    int 0x80        ;call write function

    mov eax, 4      ;write message about double
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, msg4   ;set the pointer to msg4
    mov edx, len4   ;set the length to len4
    int 0x80        ;call write function

    mov eax, 4      ;write contents of input2
    mov ebx, 1      ;use the default output device (print in terminal)
    mov ecx, input2 ;set the pointer to input2
    int 0x80        ;call write function

_exit:
    mov eax, 1      ;standard exit
    mov ebx, 0      ;0 is normal
    int 0x80

Ответы [ 2 ]

1 голос
/ 16 февраля 2012

Когда вы читаете ввод, кажется, что вы забыли указать длину для чтения:

mov eax, 3      ;select the kernel read function
mov ebx, 0      ;use the default input device (user txt input)
mov ecx, input  ;pointer to input variable
int 0x80        ;invoke kernel read function

I предполагает , что старое значение edx будет иметь длину read(2) - что будет намного длиннее, чем ваше input пространство. (И пять байт? Конечно кажется странным. Кроме того, комментарий, кажется, не соответствует коду, но это может быть моим незнанием больше, чем ваш код.)

0 голосов
/ 16 февраля 2012

Позвольте мне понять это правильно:

  1. Вы читаете строку как ввод
  2. Вы помещаете его в регистр (на самом деле 32-битный регистр достаточно широк, чтобы содержать строку из 4 символов)
  3. Вы переинтерпретируете строку как целое число (здесь вам действительно нужно преобразовать из десятичного в двоичное)
  4. Вы делите пополам / вдвое
  5. Вы отправляете бессмысленный поток пополам символов на выход
  6. Вы получаете мусор на экране.

Вам необходимо преобразовать полученную строку ASCII из десятичной в двоичную и обратно перед вводом и выводом. Если вы не используете atoi() или аналогичный, вы можете написать свою собственную версию, на самом деле это не так сложно.

Вам необходимо зарезервировать больше байтов для строк, 32-битное число может быть длиной до 10 символов. Если бы вы это сделали, вы, вероятно, сами видели там ошибку, потому что вам, возможно, было бы трудно сжать 10-байтовую строку в 32-битный регистр.

...