Jak kilka razy wpisywać tekst do bufora?

0
org 100h

start:
		mov cx, 3
	petla:
		mov ah, 09h
		mov dx, Tekst
		int 21h
		
		mov ah, 0ah
		mov dx, bufor
		int 21h
		
		call nl
		
		mov ah, 09h
		mov dx, bufor+2
		int 21h
		
		call nl
		
		loop petla

		mov ax, 4c00h
		int 21h
		
		Tekst	db "Podaj tekst: $"
		
		bufor	db 20
			db 0
			times 22 db "$"
		
		nl:
			mov ah, 09h
			mov dx, nowalinia
			int 21h
		ret
		nowalinia db 10, 13, "$"

Chciałbym w ten sposób wpisywać tekst do bufora ale po każdym przejściu pozostają jakieś śmieci i program działa tak:
Podaj tekst: qwerty
qwerty
Podaj tekst: asd
tyd
Podaj tekst: cxzv
yxzv

Nie wiem jak zrobić aby za każdym razem wyświetlało poprawny tekst który został wpisany.
Proszę o pomoc. Używam NASM i program pisany dla DOS, 16 bitowy.

1

Program robi dokładnie to co napisałeś… ;-)

nowalinia db 10, 13, "$"

nie 10,13 tylko 13,10

bufor db 20
db 0

w tym bajcie db 0 DOS zapisuje ilość znaków wczytanych. musisz zerować wartość przed każdym nowym wczytywaniem

1

wylicz sobie adres początku buforu instrukcją lea później począwszy od tego miejsca wsadz tak dużo bajtów zerowych ile się da. Poczytaj sobie o instrukcjach typu rep albo użyj po prostu memset z języka C do wypełnienienia zadanego obszaru zerami.

2

Kod źródłowy:

org 100h
 
start:
	mov cx, 3 ;pętla wykona 3 iteracje
	petla:
		dec cx ;zmniejsz o 1 licznik pętli
		mov ah, 09h ;funkcja wyświetlają napis
		mov dx, Tekst ;do dx kopiujemy adres napisu
		int 21h ;wywołujemy przerwanie
		 
		mov ah, 0Ah ;funkcja buforowanego wejścia
		mov dx, bufor ;do dx kopiujemy adres bufora
		int 21h ;wywołujemy przerwanie
		 
		call nl ;wywołujemy podprogram wypisujący znak nowej linii
		
		xor dx, dx ;czyścimy rejestr dx
		mov dl,[bufor+1] ;przesunięcie 1 bufora zawiera liczbę znaków
		mov bx,bufor ;do  bx adres bufora
		add bx,3 ;bx wskazuje na początek znaków bufora + 1
		add bx,dx ;bx wskazuje na koniec znaków bufora + 1
		mov byte [bx],'$' ;do bajtu na który wskazuje bx kopiujemy znak kończący napis (czyli $)
		
		mov ah, 09h ;funkcja wyświetlająca napis
		mov dx, bufor+2 ;dx wskazuje na początek znaków w buforze
		int 21h ;wywołujemy przerwanie
		 
		call nl ;wywołujemy podprogram wypisujący znak nowej linii
		
		cmp cx, 0 ;sprawdzamy czy cx == 0
	jne petla ;jeżeli nie, to wykonujemy pętlę
	 
	mov ax, 4C00h ;4C - funkcja wyjścia, 00 = kod wyjścia
	int 21h ;wywołujemy przerwanie
 
Tekst db "Podaj tekst: $"
bufor db 20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

nl:
        mov ah, 09h
        mov dx, nowalinia
        int 21h
ret
nowalinia db 13, 10, "$"

Przykładowe wyjście:

C:\DOCUME~1\Dawid\Pulpit\NASM-2~1.05>prog.com
Podaj tekst: qwerty
qwerty
Podaj tekst: asd
asd
Podaj tekst: cxzv
cxzv

C:\DOCUME~1\Dawid\Pulpit\NASM-2~1.05>
3
0DFh napisał(a):
	mov cx, 3 ;pętla wykona 3 iteracje
	petla:
		dec cx ;zmniejsz o 1 licznik pętli
	...
		cmp cx, 0 ;sprawdzamy czy cx == 0
	jne petla

Dawid, żaden coder nie testuje stanu (e)cx poprzez przyrównanie do zera, w miarę możliwości w ogóle unika się jawnego porównywania, instrukcja jecxz dla samego skoku warunkowego, loop jako odpowiednik wszystkich powyższych instrukcji, najlepiej zaś opierając skok warunkowy na zmianach flag po wykonanej operacji, dla tak użytego dec byłoby to js.

@Papec, @0DFh, nie mieszajcie kodu z danymi, chociaż dla czytelności, to naprawdę pomaga.

0DFh napisał(a):
		mov bx,bufor ;do  bx adres bufora
		add bx,3 ;bx wskazuje na początek znaków bufora + 1
		add bx,dx ;bx wskazuje na koniec znaków bufora + 1
		mov byte [bx],'$'

Tak się NIE adresuje w trybie 16 bit :| Nawet bez użycia prefiksu address-size override można to wszystko załatwić JEDNĄ instrukcją, do tego właśnie służą rejestry indeksowe i rejestr bazowy. Całość można zapisać pojedynczą instrukcją jeżeli tylko wybierze się ODPOWIEDNI rejestr do przechowywania indeksu.

0DFh napisał(a):
		mov ah, 09h ;funkcja wyświetlają napis
		mov dx, Tekst ;do dx kopiujemy adres napisu
		int 21h ;wywołujemy przerwanie
        ...
		call nl ;wywołujemy podprogram wypisujący znak nowej linii
        ...
		mov ah, 09h ;funkcja wyświetlająca napis
		mov dx, bufor+2 ;dx wskazuje na początek znaków w buforze
		int 21h ;wywołujemy przerwanie
		 
		call nl ;wywołujemy podprogram wypisujący znak nowej linii
        ...
nl:
        mov ah, 09h
        mov dx, nowalinia
        int 21h

Można było podejść zdecydowanie lepiej: jeżeli już posługujemy się dodatkowymi funkcjami to fajnie by było zbudować sobie z nich sensowne abstrakcje, poza nową linią na pewno powinno być to wypisywanie stringa na ekran, co można uzyskać za nawet darmo. Po uwzględnieniu powyższych uwag:

org 100h

start:
    mov     cx, 3 
main_loop:
    mov     dx, prompt 
    call    print

    mov     ah, 0Ah 
    mov     dx, buffer 
    int     21h 
    
    call    print_newline 
    
    xor     bx, bx
    mov     bl, [buffer+1]
    mov     byte [buffer+bx+3], '$'
    
    mov     dx, buffer+2 
    call    print

    call    print_newline 
    
    loop    main_loop

    mov     ax, 4C00h 
    int     21h 
    
print_newline:
    mov     dx, newline
print:
    mov     ah, 09h
    int     21h
    retn

newline     db 13, 10, "$"
prompt      db "Podaj tekst: $"
buffer      db 20

Jest różnica? Jak tak na to patrzę to chyba powinienem napisać książkę o assemblerze...

1 użytkowników online, w tym zalogowanych: 0, gości: 1