2013-03-16 23 views
5

Quindi ho la maggior parte del codice funzionante, ma non riesco a capire esattamente come affrontare il fatto che la frase di input è di una lunghezza sconosciuta. Sono nuovo all'assemblaggio e questo è un po 'confuso.Come gestire l'input di lunghezza sconosciuta in ASM x86?

(In questo momento l'ho impostato come se la lunghezza erano noti per essere tre personaggi, ma ovviamente ho bisogno di cambiare la situazione.)

.data  
input_msg: .ascii "Enter a random sentence: " 
input_msg_len: .long 25 
input_str: .ascii "???" # 3rd should get newline 
count:  .long 0 
newline: .long 10  

.text    
.global _start   
_start:    

# prompt for input 
    mov $4, %eax # prompt for input 
    mov $1, %ebx 
    mov $input_msg, %ecx 
    mov input_msg_len, %edx 
    int $0x80 
# get input 
    mov $3, %eax # 3 to request "read" 
    mov $0, %ebx # 0 is "console" (keyboard) 
    mov $input_str, %ecx # input buffer addr 
    mov $3, %edx # number of symbols typed in 
    int $0x80  # Go do the service! 

again1: 
    mov $input_str, %ecx  
    add count, %ecx # count is offset from input_str beginning 

    mov $4, %eax # to write 
    mov $1, %ebx # to console display 
    mov $1, %edx # 1 byte to write 
    int $0x80 # Do it! 

    push %ecx  # push onto stack 

    incl count # increment count 

    cmp $3, count # compare lengths 
    jnz again1  # jmp again if not 0 (no difference) 

    mov $0, %edi # use edi as loop counter 

    mov $4, %eax # print out msg 
    mov $1, %ebx # etc. 
    mov $1, %edx # length 
    int $0x80  # OS, serve! 

again2:  
    pop %ecx  

    mov $4, %eax # print out msg 
    mov $1, %ebx # etc. 
    mov $1, %edx # length 
    int $0x80  # OS, serve!   

    inc %edi # increment edi 
    cmp count, %edi # compare lengths 
    jnz again2 # jmp again if not 0 (no difference) 

# print newline 
    mov $4, %eax # print out msg 
    mov $1, %ebx # etc. 
    mov $newline, %ecx # addr 
    mov $1, %edx # length 
    int $0x80  # OS, serve! 
# exit 
    mov $1, %eax # exit 
    int $0x80  # OS, serve!  

In sostanza, quello che voglio sapere è come faccio ottenere il codice per funzionare per qualsiasi frase, piuttosto che solo una lunghezza di 3 caratteri?

+0

Null termina la stringa. O è necessario memorizzare la lunghezza da qualche parte. – nhahtdh

+1

Cos'è l'interrupt $ 80? Penso che questo fosse riservato per la ROM di base. Dovrai dire all'ambiente che stai programmando prima che qualcuno possa aiutarti. – Gene

+0

@Gene Int 80h viene utilizzato dai sistemi unix-like per le chiamate di sistema. È un po 'come Int 21h sotto MS-DOS/Windows. – mjv

risposta

1

È sufficiente allocare un buffer più lungo per input_str e leggere la quantità di testo effettivamente letto, trovata in eax dopo la lettura syscall.

In altre parole, è necessario decidere in merito alla lunghezza massima si dovrebbe accettare e cambiare il codice a qualcosa di simile al seguente:
Nota: è ok per assegnare le stringhe brevi come questo, staticamente, naturalmente se avevi bisogno di un grande buffer (per esempio per ottenere i dati da un file), puoi invece allocare il buffer in modo dinamico). Di nuovo, per l'input da tastiera 132 è probabilmente adeguato.

... 
input_str: db 132 dup(?) # 132 bytes buffer for input string 
input_str_len: .long  # length of the string effectively read from user 
... 
# get input 
    mov $3, %eax # 3 to request "read" 
    mov $0, %ebx # 0 is "console" (keyboard) 
    mov $input_str, %ecx # input buffer addr 
    mov $131, %edx # _Max_ number of bytes accepted in input_str 
    int $0x80  # Go do the service! 

    move %eax, $input_str_len # save nb of bytes effectively read 
... 
    #you can then use input_str_len to control when to exit processing loop etc. 
+0

Come potrei fare per farlo? E quanto tempo faccio il buffer se non so per quanto tempo è la frase? – Cat

+0

Non sono riuscito a far funzionare la parte "db 132 dup (?)", Ma mi ha aiutato a capire come contare i byte, quindi grazie! – Cat

+0

domanda noob, 'mov% rax, $ input_str_len' espressa in sintassi Intel? Ricevo il messaggio _ "combinazione non valida di opcode e operandi" _ quando scrivo 'mov input_str_len, rax' – akst

0

Beh ... si potrebbe fare uno sys_brk con %ebx = 0. Questo è il tuo "rottura" originale - salvarlo. Aggiungi qualche multiplo di 4k a quel valore e sys_brk di nuovo. Fai il tuo sys_read in quel buffer. Se leggi l'intero 4k (in %eax dopo il sys_read), aggiungi di nuovo un po 'di più alla tua "pausa" e sys_brk corrente, poi leggi un po' di più ... fino a quando non finisci. Questo "dovrebbe" darti tutto in un buffer contiguo ...

Heck di molto più facile solo per decidere su alcuni "max" e non lasciarli entrare più di così! Si consiglia di "svuotare il buffer". Come sapete, sys_read (dalla tastiera) non tornerà finché non vedrà un linefeed (0xA). Se l'utente fastidioso ha digitato più di %edx caratteri, il resto rimane nel buffer del SO. Puoi vedere questo nel tuo codice buffer a 3 byte. Digita "abcls". Penso che scoprirai che il comando "ls" viene letto dal prompt della shell dopo l'uscita e ti fornisce un elenco di directory. Nessun problema, ma potrebbe essere "rm" o qualcosa di dannoso! Quando il tuo sys_read ritorna, se %eax è inferiore a %edx, hai finito. Se %eax = %edx (non sarà più), se l'ultimo carattere nel buffer è LF (0xA), il gioco è fatto. In caso contrario, sys_read in un buffer fittizio finché non si ottiene quel LF. Questo complica il codice molto, ma è "più sicuro" ...

ho potuto provare un esempio nella sintassi Nasm, ma non credo che farei meglio tentativo & T ... :)

+0

Scusa, sono un po 'confuso riguardo a ciò che stai descrivendo (il mio professore non ha spiegato cosa rappresenta realmente il codice).Voglio dire, capisco cosa intendi facendo un max, ma non penso che dovremmo avere un max. Poi di nuovo l'unica descrizione di cosa fare è "Questo richiede la lettura di un singolo carattere ripetutamente in un ciclo, e lo spingo nella pila di memoria, finché non viene premuto il tasto" invio "(carattere di nuova riga). loop, un contatore (può usare il registro edi) conta quante lettere sono state digitate fino ad ora. " e non sono abbastanza sicuro di cosa voglia dire. – Cat

+0

Ho capito che LF (0xA) è la "new" cosa di "invio". Anche se questo mi porta un errore che dice "Errore di segmentazione (core dumped)". – Cat

Problemi correlati