PDA

View Full Version : [Assembly] Stampare Stringa Alla Rovescio


dengel_1
27-02-2007, 20:22
Ho un problema..il programma stampa oltre alla stringa ribaltata anche
faccine varie . E ed U..ovvero codice ascii casuali..come posso risolvere?
vi posto il codice..:mad:


.MODEL TINY
.CODE
ORG 0100h

START: jmp MAIN

STRINGA db 5,0,0,0,0,0,0


;----------------------------------------------------------------------------

MAIN PROC

;input stringa
mov ah,0ah
lea dx,STRINGA
int 21h

;stampa stringa
lea bx, STRINGA
inc bx
mov cx,0
mov cl,[bx]
inc bx
mov ah,2; stampa

;stampa stringa al contrario


Ribaltamento:


mov ch,0
lbl_a: mov cl,[bx]
mov dl,[bx]
inc bx
loop lbl_a
mov ch,0
mov cl,dl
lbl_r: mov dl,[bx]
mov ah,2
int 21h
dec bx
loop lbl_r
lbl_s: mov dl,[bx]
mov ah,2
int 21h
dec bx
loop lbl_s

int 20h
MAIN ENDP
;----------------------------------------------------------------------------
END START
END

okay
28-02-2007, 07:56
non ho provato il code ma prova a dichiarare la stringa così:
STRINGA DB "mia stringa",'$'

probabilmente ti stampa segno strani, cuoricini e faccine perchè hai messo lo 0 finale alla stringa con il tasm devi limitarla con il '$' finale.

andbin
28-02-2007, 08:42
prova a dichiarare la stringa così:
STRINGA DB "mia stringa",'$'Lui non deve mettere una stringa "literal", in quanto usa il servizio 0Ah/int 21h che effettua l'input di una stringa. Il buffer deve essere impostato con 2 byte di "header" come spiegato <qui> (http://www.ctyme.com/intr/rb-2563.htm).

probabilmente ti stampa segno strani, cuoricini e faccine perchè hai messo lo 0 finale alla stringa con il tasm devi limitarla con il '$' finale.Il tasm non c'entra nulla. Il '$' va usato come terminatore di una stringa solo quando si usa il servizio 09h/int 21h (che lui non ha usato).

Ho un problema..il programma stampa oltre alla stringa ribaltata anche
faccine varie . E ed U..ovvero codice ascii casuali..come posso risolvere?Il sorgente è un po' confuso ... ci sono istruzioni a mio avviso inutili.
Se vuoi stampare una stringa rovesciata, hai 2 possibilità: rovesciare fisicamente la stringa nel buffer e quindi stamparla, oppure stampare semplicemente i caratteri partendo dall'ultimo verso il primo.

Se non ci sono richieste/necessità particolari, consiglierei il secondo modo. Una volta che in CX hai la lunghezza della stringa e BX punta al byte che contiene la lunghezza, basta sommare CX a BX, quindi finché CX è diverso da 0 stampare il carattere in [BX] e decrementare BX e CX.
Verrebbe circa la metà di quanto hai scritto ...

EDIT: Invece di usare BX e CX si potrebbe usare SI come base e BX come offset, usando il modo di indirizzamento [BX+SI]. Sarebbe ancora meglio!!

dengel_1
28-02-2007, 12:44
BX punta al byte che contiene la lunghezza,

Come faccio a puntare bx al byte contenente la lunghezza?

per sommare poi

JZ lbl_somma



lbl_somma: ADD bx,cx
DEC cx
DEC bx

Ho cercato di tradurre in codice quello che mi hai detto..ora ci vorrebbe un tuo aiuto nel collegare tutto quanto :)

andbin
28-02-2007, 13:07
Ho cercato di tradurre in codice quello che mi hai detto..ora ci vorrebbe un tuo aiuto nel collegare tutto quanto :)Guarda ... è abbastanza semplice. Nel tuo codice hai usato BX che punta inizialmente al primo byte del buffer e CX come contatore (la parte bassa la prendi dal secondo byte del buffer).

Nell'EDIT ho detto che si può usare l'indirizzamento . In effetti non mi è venuto in mente subito ma consentirebbe di eliminare alcune istruzioni.
In sostanza usi SI per puntare al buffer e il contatore dei caratteri lo metti in BX. Cambia poco dal tuo, solo i registri.
Poi però se SI lo lasci che punta al secondo byte (quello della lunghezza restituita), facendo [BX+SI] prendi il carattere dall'ultimo fino al primo.

Ad ogni ciclo verifichi [B]prima che BX sia uguale a zero e se lo è esci dal ciclo. Altrimenti prendi il carattere con [BX+SI], lo stampi e quindi decrementi BX e ripeti il ciclo.

dengel_1
28-02-2007, 14:37
Siccome a scuola non abbiamo mai usato si, è meglio utlizzare i reigstir utilizzati fino ad ora..visto che è un esercitazione da consegnare :)

Non potendo usare si, devo utilizzare esclusivamente i registri
cx,bx,dx e ax..

Nel mio caso Bx= primo byte

Ma non capisco come fare a dirgli..Leggi a partire dall' ultimo byte di bx( senza usare si ovviamente)..grazie x la disponibilità :)

andbin
28-02-2007, 14:54
Ma non capisco come fare a dirgli..Leggi a partire dall' ultimo byte di bx( senza usare si ovviamente)..grazie x la disponibilità :)Uh ... ok, allora non usiamo SI. ;)

Se in CX hai il numero di caratteri e BX sta puntando al secondo byte del buffer, basta che sommi CX a BX. Poi nel loop dovrai decrementare sia BX che CX.

dengel_1
28-02-2007, 18:00
Ribaltamento:
add cx,bx

jz
lbl_b: dec bx
dec cx
loop
mov cx,[bx]
mov ah,2

E ora nel codice? come fare a mettere in pratica quello che hai detto tu? :muro:

pisto
28-02-2007, 19:08
mi consigliate una guida per super principianti per l'assembly? si intende x86, e che sia possibilmente aggiornata e gratis

andbin
28-02-2007, 19:29
Ribaltamento:
add cx,bx

jz
lbl_b: dec bx
dec cx
loop
mov cx,[bx]
mov ah,2

E ora nel codice? come fare a mettere in pratica quello che hai detto tu? :muro:No no .. alt. Intanto ho detto di sommare CX a BX, non il contrario. Poi nel loop innanzitutto bisogna controllare che CX sia diverso da zero (lo puoi fare con una CMP o anche con una OR su sé stesso). Se è zero, esci dal ciclo. Poi metti in DL il carattere (cioè [BX]), chiami il servizio 02H/int 21H, quindi decrementi BX e CX e ripeti da capo.

okay
28-02-2007, 23:05
allora ecco:



SEG_A SEGMENT
ASSUME CS:SEG_A, DS:SEG_A
ORG 100H

Ribalta PROC FAR

inizio: jmp START ;salta a START

max_len EQU 1000 ;massima lunghezza
sorgente db max_len dup(?) ;stringa da ribaltare
destinaz db max_len dup(?) ;stringa ribaltata

START:
mov si,OFFSET sorgente
prossimo_car: mov ah,01h ;legge un car dalla tastiera
int 21h
cmp al,0Dh ;è = a return ?
je fine_lettura ;se si smetti di leggere
mov sorgente[si],al ;sposta il carattere in sorgente
inc si ;incrementa si
jmp prossimo_car ;leggi il prossimo car



fine_lettura:
mov cx,si
push cx ;memorizza la lunghezza nello stack
mov bx,OFFSET sorgente
mov si,OFFSET destinaz
add si,cx ;metto in si la lunghezza della stringa
dec si ;decrementa si

Ribaltamento:
mov al,[bx] ;routine di ribaltamento
mov [si],al ; parto dal fondo e la copio
inc bx ; in destinaz
dec si
loop Ribaltamento ; salto a Ribaltamento

pop si ;prelevo la lunghezza
mov destinaz[si+1],'$' ;aggiungo il terminatore
mov ah,09h
mov dx,OFFSET destinaz
int 21h ;stampo la stringa ribaltata

RETN
Ribalta ENDP

SEG_A ENDS
END inizio

dengel_1
01-03-2007, 13:18
Quello che mi hai postato utilizza si..e cmq l'avevo già trovato..non fa al caso mio..


Ok il programma stampa la stringa rovesciata ma con 3 faccine(che progresso :D ) Come mai?


;Ribaltamento
add bx,cx

lbl_b: cmp cx,0
je lbl_fine
mov dl,[bx]
dec bx
dec cx
int 21h
loop lbl_b


lbl_fine:
int 20h

andbin
01-03-2007, 13:29
Ok il programma stampa la stringa rovesciata ma con 3 faccine(che progresso :D ) Come mai?metti un jmp lbl_b invece di loop.

Si potrebbe anche benissimo usare l'istruzione loop ma a quel punto dovresti: a) togliere dec cx (lo fa già loop) e b) la comparazione di cx con 0 la puoi fare solo una volta fuori dal ciclo.

okay
01-03-2007, 16:57
mi consigliate una guida per super principianti per l'assembly? si intende x86, e che sia possibilmente aggiornata e gratis

http://xoomer.virgilio.it/ramsoft/

dengel_1
01-03-2007, 18:33
Ho provato a mettere il jmp ma purtoppo se inserisco 123 mi stampa 323 e il programma termina..ci siamo quasi?:rolleyes:

dengel_1
02-03-2007, 18:35
non funge :mad:

andbin
02-03-2007, 19:25
non funge :mad:Riposta il codice completo che vediamo.

dengel_1
02-03-2007, 19:49
; Assemblaggio come .COM:
; TASM [nomefile.ASM]
; TLINK [nomefile.OBJ] /t
;---------------------------------------------------------------------------
.MODEL TINY
.CODE
ORG 0100h

START: jmp MAIN

STRINGA db 5,0,0,0,0,0,0


;----------------------------------------------------------------------------

MAIN PROC

;input stringa
mov ah,0ah
lea dx,STRINGA
int 21h

;stampa stringa
lea bx, STRINGA
inc bx
mov cx,0
mov cl,[bx]
inc bx
mov ah,2; stampa

;stampa stringa al contrario



Ribaltamento:
add bx,cx

lbl_b: cmp cx,0
je lbl_fine
mov dl,[bx]
dec bx
dec cx
int 21h
jmp lbl_b


lbl_fine:
int 20h
MAIN ENDP
;----------------------------------------------------------------------------
END START
END

andbin
02-03-2007, 20:03
lea bx, STRINGA
inc bx
mov cx,0
mov cl,
[B]inc bxQuest'ultima inc bx non ci deve essere. L'avevo anche detto ... "Se in CX hai il numero di caratteri e BX sta puntando al secondo byte del buffer..."

dengel_1
02-03-2007, 20:22
Si vede che sei un programmatore esperto :D

Ora funziona... grazie :D

dengel_1
02-03-2007, 20:30
Pero' ho un altro problema..
All'inizio del prog ho inserito dei messaggi obbligatori da scivere


MSG1INPUT db "MIONOME",0
MSG2INPUT db 0Dh,0Ah, "E03",0
MSG3INPUT db 0Dh,0Ah,"ROVESCIATO",0
MSG4INPUT db 0dh,0ah,"INSERIRE STRINGA",0
MSG5INPUT db 0dh,0ah,"ROVESCIATA",0

e per richiamare il primo all'inizio dopo il main scrivo

lea bx,MSG1INPUT

Eppure lui lo ignora richiamando l'input..come mai?

andbin
03-03-2007, 12:49
Pero' ho un altro problema..
All'inizio del prog ho inserito dei messaggi obbligatori da scivere


MSG1INPUT db "MIONOME",0
MSG2INPUT db 0Dh,0Ah, "E03",0
MSG3INPUT db 0Dh,0Ah,"ROVESCIATO",0
MSG4INPUT db 0dh,0ah,"INSERIRE STRINGA",0
MSG5INPUT db 0dh,0ah,"ROVESCIATA",0

e per richiamare il primo all'inizio dopo il main scrivo

lea bx,MSG1INPUT

Eppure lui lo ignora richiamando l'input..come mai?Se vuoi stampare una stringa puoi usare il servizio Int 21H/AH=09H.
MOV AH,09H
MOV DX,OFFSET stringa
INT 21HE nota bene che la stringa deve terminare con un '$' (codice 36)

dengel_1
03-03-2007, 14:40
SI grazie ho risolto..ciao :D :D :D :D