Въведете неправилно събрание x86 NASM

Гледам това от часове и не мога да разбера защо след второто ми въвеждане моят низ, съхранен от първото въвеждане, се променя.

Когато стартирам проба, стартирайте така:

Моля, въведете id: 12

Моля, въведете името: jay

Когато стартирам тази част от кода само за стандартно въвеждане и извеждане, 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, след което също така помислете за null, завършващ низа, съхранен в id1Buf.   -  person alvonellos    schedule 26.03.2014
comment
@alvonellos, когато промених на 4 id1Buf става 12\n\000jay\n ако прекратя null, 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

TL;DR: Трябва да опитате да преработите този клас, така че self.create_network() да се извиква (i) само веднъж и (ii) преди tf.train.Saver() да бъде конструиран.

Тук има два фини проблема, които се дължат на структурата на кода и поведението по подразбиране на tf.train.Saver конструктор. Когато конструирате спасител без аргументи (както във вашия код), той събира текущия набор от променливи във вашата програма и добавя операции към графиката за запазването и възстановяването им. Във вашия код, когато извикате tflasso(), той ще създаде предпазител и няма да има променливи (тъй като create_network() още не е извикан). В резултат на това контролно-пропускателният пункт трябва да е празен.

Вторият проблем е, че по подразбиране форматът на запазена контролна точка е карта от name свойство на променлива към текущата й стойност. Ако създадете две променливи с едно и също име, те ще бъдат автоматично "уникални" от TensorFlow:

v = tf.Variable(..., name="weights")
assert v.name == "weights"
w = tf.Variable(..., name="weights")
assert v.name == "weights_1"  # The "_1" is added by TensorFlow.

Последствието от това е, че когато извикате self.create_network() във второто извикване на tfl.fit(), всички променливи ще имат различни имена от имената, които се съхраняват в контролната точка, щяха да бъдат, ако спасителят беше конструиран след мрежата. (Можете да избегнете това поведение, като подадете речник name-Variable към конструктора на saver, но това обикновено е доста неудобно.)

Има две основни решения:

  1. При всяко извикване на tflasso.fit(), създайте целия модел наново, като дефинирате нов tf.Graph, след което в тази графика изградете мрежата и създайте tf.train.Saver.

  2. ПРЕПОРЪЧИТЕЛНО Създайте мрежата, след това tf.train.Saver в конструктора tflasso и използвайте отново тази графика при всяко извикване на tflasso.fit(). Имайте предвид, че може да се наложи да свършите още малко работа, за да реорганизирате нещата (по-специално, не съм сигурен какво правите с self.X и self.xlen), но трябва да е възможно да постигнете това с заместители и захранване.

  -  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