Введена неверная сборка x86 NASM

Я смотрел на это часами и не могу понять, почему после моего второго ввода моя строка, сохраненная из первого ввода, изменяется.

Когда я запускаю пробный запуск следующим образом:

Пожалуйста, введите идентификатор: 12

Пожалуйста, введите имя: Джей

Когда я запускаю эту часть кода только для стандартного ввода и вывода, gdb показывает, что id1Buf имеет значение «12\n» после первого чтения. Затем он предлагает ввести имя, поэтому, когда я ввожу jay, значение id1Buf по какой-то причине меняется на «12\njay». Не могу разобраться, было бы здорово, если бы кто-нибудь помог.

SECTION .text                               ;.text section

global _start                               ;start section

_start:                                     ;start
    main:     
        ;;write out
        mov eax, SYSCALL_WRITE              ;write function
        mov ebx, STDOUT                     ;write value
        mov ecx, id                         ;address of message
        mov edx, lenid                      ;length of message
        int 80h                             ;interrupt

        ;;read user input
        mov eax, SYSCALL_READ               ;read function
        mov ebx, STDIN                      ;read in value
        mov ecx, id1Buf                     ;store read value in id1Buf
        mov edx, IDBUFLEN                   ;length of idbuf
        int 80h                             ;interrupt

        ;;write out
        mov eax, SYSCALL_WRITE              ;write function
        mov ebx, STDOUT                     ;write value
        mov ecx, name                       ;address of message
        mov edx, lenname                    ;length of message
        int 80h                             ;interrupt

        ;;read user input
        mov eax, SYSCALL_READ               ;read function
        mov ebx, STDIN                      ;read in value
        mov ecx, name1Buf                   ;store read value in name1Buf
        mov edx, NAMEBUFLEN                 ;length of namebuf
        int 80h                             ;interrupt

        mov [name1readlen], eax             ;store length of name

Это какой-то другой код для справки.

;;constants 
%define STDIN 0                             ;read function
%define STDOUT 1                            ;write function
%define STDERR 2                            ;error function
%define SYSCALL_EXIT 1                      ;exit 
%define SYSCALL_READ 3                      ;read
%define SYSCALL_WRITE 4                     ;write
%define IDBUFLEN 3                          ;length of id buffer
%define NAMEBUFLEN 500                      ;length of name buffer

;;given data
SECTION .data
    id db "Please enter the id: "           ;prompt for id
    lenid equ $-id                          ;length of id prompt

    name db "Please enter the name: "       ;prompt for name
    lenname equ $-name                      ;length of name

    idlabel db "ID:    "                    ;used for printing end data
    lenidlabel equ $-idlabel                ;length of id label

    namelabel db "NAME: "                   ;used for printing end data
    lennamelabel equ $-namelabel            ;length of name label

    printline db "", 10                     ;new line character


;;unintialized data
SECTION .bss
    id1Buf:        resb IDBUFLEN             ;buffer for id 1
    name1Buf:      resb NAMEBUFLEN           ;buffer for name 1

person Captain Gh0st    schedule 26.03.2014    source источник
comment
Скажите, что произойдет, если вы измените resb IDBUFLEN на 4 или 5 вместо 3, а затем также рассмотрите возможность нулевого завершения строки, хранящейся в id1Buf.   -  person alvonellos    schedule 26.03.2014
comment
@alvonellos, когда я изменил на 4, id1Buf становится 12\n\000jay\n, если я завершаю его нулем, id1Buf становится 12\000\000jay\n   -  person Captain Gh0st    schedule 26.03.2014
comment
Они работают вместе из-за какого-то условия смещения, попробуйте использовать equ вместо %define для этой константы и скажите мне, что произойдет.   -  person alvonellos    schedule 26.03.2014
comment
@alvonellos извините, я новичок в этом языке, вы поместили это в раздел .data? как бы ты это сделал IDBUFLEN equ 2   -  person Captain Gh0st    schedule 26.03.2014
comment
Синтаксис правильный, но я считаю, что вы поместили его туда, где у вас есть свои определения. Кроме того, когда вы сохраняете значение в этом неинициализированном разделе данных, переместите его в какую-либо переменную памяти и работайте с ним оттуда.   -  person alvonellos    schedule 26.03.2014
comment
Я тоже новичок в NASM. Когда я изучал сборку в колледже, я выбрал MASM.   -  person alvonellos    schedule 26.03.2014
comment
@alvonellos происходит то же самое, это так странно, что они работают вместе, потому что я явно не использую id1Buf снова во втором чтении. это будет похоже на очень маленькую проблему, которую трудно найти.   -  person Captain Gh0st    schedule 26.03.2014
comment
@alvonellos да, я беру это на курс колледжа прямо сейчас   -  person Captain Gh0st    schedule 26.03.2014
comment
Ваши буферы непрерывны, что вы ожидаете от этого?   -  person Frank Kotler    schedule 26.03.2014
comment
@FrankKotler, лол, извините, я довольно тупой, как бы вы это исправили, я думал, что создал буферы отдельно?   -  person Captain Gh0st    schedule 26.03.2014
comment
Я не вижу, что это нуждается в исправлении. Скажите gdb отображать меньше, возможно?   -  person Frank Kotler    schedule 26.03.2014
comment
@FrankKotler это способ, но у меня есть «10 таких буферов» id1Buf: resb IDBUFLEN id2Buf: resb IDBUFLEN как лучше всего сохранить все эти пользовательские данные для удобного редактирования / манипулирования позже?   -  person Captain Gh0st    schedule 26.03.2014


Ответы (1)


Аааа, позвольте мне сделать это «ответом» (хотя я не уверен, что это так). То, что вы видите, является ожидаемым поведением. У вас есть трехбайтовый буфер, вы заполнили его «1», «2» и «\n». Сразу после этого у вас есть еще один (более длинный) буфер, в который вы помещаете «J», «a», «y» и «\n».

Notice that sys_read terminates your input with a linefeed (\n), not a zero. It won't return until "enter" is hit. (this applies to STDIN - other files differ) You've got a bigger problem if the pesky user enters "12345(enter)", The first buffer will get '1', '2', '3' - it won't overflow - but after the "name" prompt, it won't pause but '4', '5', '\n' will be put into the name buffer. The solution is to make sure you have the linefeed!

; your sys_read
int 80h
push eax ; probably want to save the original length
checkLF:
cmp byte [ecx + eax - 1], LF
jz goodread
mov ecx, dummybuf ; to be thrown away
mov edx, 1
mov ebx, STDIN ; still in there, probably
mov eax, SYSCALL_READ
int 80h
jmp checkLF
goodread:
pop eax  ; get original length back

You may wish to zero-terminate the string(s). (maybe should have saved original ecx too) sys_write doesn't expect a zero-terminated string, but we can find the length and put it in edx.

mov ecx, buffer ; maybe a parameter?
xor edx, edx
getlen:
cmp byte [ecx + edx], 0
jz gotlen
inc edx
jmp getlen
gotlen:
; rest of your sys_read

You ask in a comment how to handle multiple inputs. I'd consider an array of pointers to name strings and an array of pointers to id strings. Possibly an array of lengths (for each?). Take small steps...

idarray dd id1buf, id2buf, id3buf, id4buf...
namearray dd name1buf, name2buf, name3buf...
; ...
mov edi, which customer we want
mov esi, [namearray + edi * 4]
; send it off for manipulating
inc edi ; next customer
; find his id?
mov ecx, [idarray + edi * 4]
; send it off to print

Something like that, maybe?

person Frank Kotler    schedule 26.03.2014
comment
Большое спасибо, последняя часть с массивами очень помогла, теперь у меня все работает отлично. - person Captain Gh0st; 26.03.2014