comparare due stringhe in assembler...
  • In diretta da GamesVillage.it
    • News
    • -
    • In Evidenza
    • -
    • Recensioni
    • -
    • RetroGaming
    • -
    • Anteprime
    • -
    • Video
    • -
    • Cinema

Visualizzazione risultati da 1 a 13 di 13

Discussione: comparare due stringhe in assembler...

Cambio titolo
  1. #1
    Utente L'avatar di aerox
    Registrato il
    10-02
    Messaggi
    5.650

    Infelice comparare due stringhe in assembler...

    Ho un problema in assembler...

    In pratica devo far si che una parola che viene inserita vada in una variabile strutturata, dopo devo confrontare questa parola inserita contenuta nella variabile strutturata con una stringa già presente in memoria.

    String db 4 (?) <- e questa è la variabile strutturata vuota

    stringa2 db 'gggg' <- questa è la stringa già in memoria.


    Il problema arriva appunto quando devo fare il confronto.. A riempite la variabile strutturata mi riesce.

    Io avrei fatto così :

    mov bx,offset stringa
    mov bp,offset stringa2

    poi avrei fatto un ciclo così :

    mov cx,4
    casa:
    cmp [bx+di],[bp+si]
    inc si
    inc di
    loop casa


    Il problema è che mi da errore sul cmp..... Mi sapete dire dove sbaglio ?

    Mi serve x domani a scuola che ho compito..

    Gazie !

  2. #2
    Security admyn ^__^ L'avatar di nuk3r
    Registrato il
    12-05
    Località
    Berghem!
    Messaggi
    287
    che errore ti da?

  3. #3
    Security admyn ^__^ L'avatar di nuk3r
    Registrato il
    12-05
    Località
    Berghem!
    Messaggi
    287
    dunque cercercherò di aiutarti anche se è un po' che non lo uso....

    innanzitutto il "linguaggio" si chiama assembly e non assembler ( assembler è il "compilatore"....o meglio, il traduttore...)

    seconda cosa, che errore ti da il cmp?

    terza cosa, per quale cpu programmi? LC-2, 8086....

    premesso che sia l'8086 (la più famosa), penso (ripeto, non sono sicuro.. )
    che il problema possa essere in

    Citazione aerox

    mov bx,offset stringa
    mov bp,offset stringa2
    in bx puoi mettere l' offset della stringa, ma non sono sicuro che tu possa in bp...o meglio puoi ma è rischioso in quanto il registro BP è il Base pointer e serve alla cpu per puntare all'interno dello stack

    prova a cambiare registro (prova dx)

  4. #4
    Utente L'avatar di aerox
    Registrato il
    10-02
    Messaggi
    5.650
    Assembling file: casa.ASM
    *Warning* casa.ASM(80) Argument needs type override
    **Error** casa.ASM(80) Illegal memory reference
    Error messages: 1
    Warning messages: 1
    Passes: 1
    Remaining memory: 470k


    Io le stringhe le ho dichiarate così :

    stringa db 4 (?)
    stringa2 db 'gggg'

    e l'errore è proprio sulla linea del cmp

    cmp [dx+di],[bx+si]

    come vedi ho seguito il tuo consiglio e ho usato dx al posto di bp

    mov dx,offset stringa2

  5. #5
    Utente L'avatar di bottomap
    Registrato il
    02-05
    Località
    Firenze
    Messaggi
    148
    Ciao,

    Il problema sta essenzialmente nel compare...

    Innanzitutto non puoi specifcare due locazioni in memoria ([bx+di],[bp+si]) per il confronto a meno di non usare l'indirizzamento del 386 (col SIB byte)

    Inoltre, anche se fosse possibile, dovrai specificare la dimensione dei dati... tra registro e memoria la dimensione &#232; indicata dal registro, ma tra memoria e memoria, l'assemblatore dovr&#224; sapere se vuoi confrontare byte,word o dword...

    Terzo, &#232; bene cercare di evitare l'uso di bp negli indirizzamenti per due motivi essenziali:
    1) L'uso di bp implica automaticamente l'utilizzo di SS come segmento (per cui sarebbe necessario un segment override)
    2) In genere bp dovrebbe essere usato (proprio perch&#233; usa implicitamente SS) per lo stack frame e le variabili locali.

    Detto questo, un codice pu&#242; essere il seguente:
    lds si,stringa1; //Oppure, se ds punta gi&#224; al segmento dati basta una lea o un mov si,offset stringa1
    lds di,stringa2; //Come sopra


    E nel ciclo:

    mov cx,4
    ciclo:
    mov al,[si]
    cmp [di],al
    jnz diversi
    inc si
    inc di
    loop ciclo

    Se vuoi mantenere i puntatori all'inzio della stringa (come facevi usando bx+si e bp+si - ma probabilmente non &#232; necessario), salvali in ax/dx (o qualsiasi altro registro di base) e trasferiscili in si e di prima di far partire il ciclo...

    Modifica: Non ho letto il post intermedio... chiedo scusa... hai fatto bene ad evitare l'uso di bp...

    Ciaociao
    Venite a visitarci qui: http://www.bottomap.com/

  6. #6
    Utente L'avatar di aerox
    Registrato il
    10-02
    Messaggi
    5.650
    ora provo a fare come hai detto te

  7. #7
    Utente L'avatar di aerox
    Registrato il
    10-02
    Messaggi
    5.650
    Citazione bottomap
    Ciao,

    Il problema sta essenzialmente nel compare...

    Innanzitutto non puoi specifcare due locazioni in memoria ([bx+di],[bp+si]) per il confronto a meno di non usare l'indirizzamento del 386 (col SIB byte)

    Inoltre, anche se fosse possibile, dovrai specificare la dimensione dei dati... tra registro e memoria la dimensione è indicata dal registro, ma tra memoria e memoria, l'assemblatore dovrà sapere se vuoi confrontare byte,word o dword...

    Terzo, è bene cercare di evitare l'uso di bp negli indirizzamenti per due motivi essenziali:
    1) L'uso di bp implica automaticamente l'utilizzo di SS come segmento (per cui sarebbe necessario un segment override)
    2) In genere bp dovrebbe essere usato (proprio perché usa implicitamente SS) per lo stack frame e le variabili locali.

    Detto questo, un codice può essere il seguente:
    lds si,stringa1; //Oppure, se ds punta già al segmento dati basta una lea o un mov si,offset stringa1
    lds di,stringa2; //Come sopra


    E nel ciclo:

    mov cx,4
    ciclo:
    mov al,[si]
    cmp [di],al
    jnz diversi
    inc si
    inc di
    loop ciclo

    Se vuoi mantenere i puntatori all'inzio della stringa (come facevi usando bx+si e bp+si - ma probabilmente non è necessario), salvali in ax/dx (o qualsiasi altro registro di base) e trasferiscili in si e di prima di far partire il ciclo...

    Modifica: Non ho letto il post intermedio... chiedo scusa... hai fatto bene ad evitare l'uso di bp...

    Ciaociao
    ma io posso incrementare direttamente il puntatore ? non devo fare un incremento del tipo bx+di ?

  8. #8
    Utente L'avatar di bottomap
    Registrato il
    02-05
    Località
    Firenze
    Messaggi
    148
    Ciao,

    Cosa intendi per "incrementare il puntatore"? SI/DI sono registri, e quindi possono essere tranquillamente incrementati...

    Se contengono un indirizzo (come, nel caso in questione, quello delle due stringhe), incrementarli significa "spostare il puntatore"...

    Al momento in cui avviene l'accesso indiretto ([si] e [di]) il valore contenuto nei registri viene visto come un puntatore ad una zona di memoria (fino ad allora &#232; un numero come tanti )...

    Visto che la stringa &#232; memoria lineare e che gli indirizzi crescono man mano che si considerano i caratteri successivi l'uso di un'indirizzamento base+indice &#232; ridondante (non sbagliato, bada bene... semplicemente non &#232; necessario a meno che non ti interessi mantenere un puntatore all'inizio delle aree di memoria in questione - in quel caso base conterr&#224;, appunto, l'indirizzo di partenza).

    [bx+si] &#232; esattamente quello che descrive... la somma dei due numeri va a formare l'indirizzo... presumibilmente BX &#232; un puntatore all'inizio di un'area di memoria ed SI l'offset da quel punto (a questo serve l'indirizzamento base+indice)... se per esempio l'area di memoria di partenza non &#232; fissa (le stringhe) ma allocata dinamicamente, &#232; possibile (anzi probabile) che tu voglia mantenere l'indirizzo di partenza da qualche parte ed operare con un indice... in caso contrario puoi evitare alla ALU un carico aggiuntivo (calcolare BX+SI) ed usare un registro solo per indirizzare la memoria.

    Ciaociao
    Venite a visitarci qui: http://www.bottomap.com/

  9. #9
    Utente L'avatar di aerox
    Registrato il
    10-02
    Messaggi
    5.650
    posto direttamente qui il rpgramma che di ostina a non funzionare,
    se qualcuno è tanto gentile da aiutarmi a trovare il xkè no funziona

    In pratica va in esecuzione. Mi fa scrivere le 4 lettere criptate con l'asterisco , ma sia che esse sono uguali che diverse dalla stringa già presente in memoria. il programma si chiude ugualmente

    Il programma è questo qui sotto.
    ---------------------------------------------------------------------
    stack_seg segment para stack 'stack'

    dw 100 dup (?)

    stack_seg ends



    data_seg segment


    stringa db (?)
    stringa2 db 'ciao'
    stringa3 db 'ERR'

    data_seg ends




    code_seg segment

    assume cs:code_seg,ds:data_seg,ss:stack_seg



    start:

    mov ax,0b800h
    mov es,ax
    mov ax,data_seg
    mov ds,ax
    mov ax,stack_seg
    mov ss,ax

    mov di,0
    mov cx,2000

    mov ax,0720h
    cld
    repz stosw


    mov bx, offset stringa

    mov si,0
    mov cx,4
    mov di,50

    ciclo: ; ciclo che inserisce i caratteri

    mov ah,00 ; in attesa di un carattere
    int 16h
    mov [bx+si],al

    mov ax,072ah ; carica gli asterisco
    inc si
    stosw
    loop ciclo



    ; procedimento x comparare le stringhe



    mov di,0
    mov si,0
    mov cx,4
    mov di,offset stringa
    mov si,offset stringa2
    compara:
    mov al,[di]
    cmp [si],al
    inc di
    inc si
    je visualizza
    jne messerr
    loop compara
    jmp visualizza

    visualizza:

    mov di,340
    mov si,0
    mov cx,4
    ciclo2:
    lodsb
    stosw
    loop ciclo2


    messerr:

    ; messaggio errore

    mov si,9
    mov cx,3
    mov di,350
    ciclo25:
    lodsb
    stosw
    loop ciclo25
    jmp chiudi


    chiudi:
    mov ax,4c00h
    int 21h

    code_seg ends
    end start

    -----------------------------------------------------------------

  10. #10
    Utente L'avatar di bottomap
    Registrato il
    02-05
    Località
    Firenze
    Messaggi
    148
    Ciao,
    Senza addentrarci troppo (lo stesso accorgimento di usare solo SI puoi applicarlo anche alla fase di input)... credo che la maggior parte dei problemi derivino dalla tua dichiarazione di stringa...

    "stringa db (?)" riserva un byte senza dargli valore... quando vai a scriverci sopra sovrascrivi quello che sta sotto. Per riservare spazio per 4 caratteri dovevi usare:
    stringa db 4 DUP(?)
    Per settarli inizialmente a zero:
    stringa db 4 DUP 0
    o pi&#249; semplicemente
    stringa db 0,0,0,0

    Il ? nelle db indica solo che non si &#232; interessati ad avere un valore iniziale (forse hai fatto confusione con la direttiva abbreviata TASM per il segmento .data? che riserva memoria al momento del caricamento, riducendo le dimensioni dell'eseguibile)... certamente non indica una stringa di dimensioni variabili.

    In pratica durante il primo input sovrascrivi il contenuto di stringa2... l'unico modo per cui poteva funzionare era se sia stringa che stringa1 contengono 4 caratteri tutti uguali...

    Se non vuoi impostare a priori la dimensione della stringa (con un valore massimo, magari) dovrai allocare la memoria necessaria, o giocare un po con lo stack frame (ad esempio impostarlo dopo aver determinato la lunghezza della stringa originaria) per "allocare" li dentro la memoria.

    Ciaociao
    Venite a visitarci qui: http://www.bottomap.com/

  11. #11
    Utente L'avatar di aerox
    Registrato il
    10-02
    Messaggi
    5.650
    ho provato a modificare quello che hai detto te. In tutte e tre le manier il risultato non cambia. Trova semrpe che le due parole sono diverse..Anche se non &#232; vero.
    Il programma modificato &#232; cos&#236;:

    ----------------------------------------------------------------

    stack_seg segment para stack 'stack'

    dw 100 dup (?)

    stack_seg ends



    data_seg segment


    stringa db 4 dup (?)
    stringa2 db 'ciao'
    stringa3 db 'ERR'

    data_seg ends




    code_seg segment

    assume cs:code_seg,ds:data_seg,ss:stack_seg



    start:

    mov ax,0b800h
    mov es,ax
    mov ax,data_seg
    mov ds,ax
    mov ax,stack_seg
    mov ss,ax

    mov di,0
    mov cx,2000

    mov ax,0720h
    cld
    repz stosw


    mov bx, offset stringa

    mov si,0
    mov cx,4
    mov di,50

    ciclo: ; ciclo che inserisce i caratteri

    mov ah,00 ; in attesa di un carattere
    int 16h
    mov [bx+si],al

    mov ax,072ah ; carica gli asterisco
    inc si
    stosw
    loop ciclo



    ; procedimento x comparare le stringhe



    mov di,0
    mov si,0
    mov cx,4
    mov si,offset stringa
    mov di,offset stringa2
    compara:
    mov al,[di]
    cmp [si],al
    inc si
    inc di
    jne messerr
    loop compara
    jmp visualizza

    visualizza:

    mov di,340
    mov si,0
    mov cx,4
    ciclo2:
    lodsb
    stosw
    loop ciclo2


    messerr:

    ; messaggio errore

    mov si,8
    mov cx,3
    mov di,350
    ciclo25:
    lodsb
    stosw
    loop ciclo25
    jmp chiudi

    ;mov ah,00
    ;int 16h
    ;cmp al,'1'
    ;je chiudi
    ;cmp al,'2'
    ;je restart

    chiudi:
    mov ax,4c00h
    int 21h

    code_seg ends
    end start

    ---------------------------------------------------------------

    Scusate se vi rompo ma ho compito domani e devo togliermi alcuni dubbietti:

    ho la finestra impostata come 80 x 25 , mi spieghi il xk&#232; se imposto DI , a 240 . Rimango sulla seconda riga ?


    Se voglio dividere lo schermo in orizzontale in diverse righe come devo fare ?
    E in verticale ?
    Ultima modifica di aerox; 1-03-2006 alle 17:48:30

  12. #12
    Utente L'avatar di bottomap
    Registrato il
    02-05
    Località
    Firenze
    Messaggi
    148
    Ciao,
    E qui arriviamo al secondo errore... in genere pi&#249; o meno tutte le istruzioni aritmetiche (compreso la inc) modificano i flag.
    Il motivo per cui a seguito della compare i salti avvengono correttamente &#232; perch&#233; la cmp modifica adeguatamente i flag... se nel mezzo finiscono delle istruzioni aritmetiche, ovviamente il risultato della cmp verr&#224; perso.

    I blocchi cmp/jmp in genere dovrebbero essere sempre istruzioni successive (anche perch&#233; il pentium e successivi riescono a sfruttare le pipeline nella maniera migliore).

    In generale, quindi le istruzioni di incremento piazzale dopo i jump e prima della loop...

    Ciaociao
    Venite a visitarci qui: http://www.bottomap.com/

  13. #13
    Utente L'avatar di aerox
    Registrato il
    10-02
    Messaggi
    5.650
    compito di oggi riuscito perfettamente , grazie !

Regole di Scrittura

  • Tu non puoi inviare nuove discussioni
  • Tu non puoi inviare risposte
  • Tu non puoi inviare allegati
  • Tu non puoi modificare i tuoi messaggi
  •