Wyświetlanie - int 21h

0

Witam
To mój pierwszy post tak więc z góry przepraszam jeśli nie dopełniłem jakiegoś obowiązku odnośnie formatu postu itp, itd
Jeśli chodzi o programowanie to jestem całkowitym amatorem, tak więc prośba o wyrozumiałość. :)
Od niedawna zacząłem zabawy z asemblerem i z pomocą książek stworzyłem coś takiego w WinAsm.
Program przetwarza bajt pobrany z klawiatury na ciąg znaków

.model tiny
.data
      liczby db "0123456789ABCDEF"
   	  znak db ?,'$'
   	  napis1 db 'Podaj znak: $'
   	  napis2 db 'Podany znak ma wartosc: $'
   	  clr db 13,10,'$'
.code  	  
	.startup
		mov dx,offset napis1	;wyswietlenie napis1
		mov ah,09
		int 21h
		
		mov ah,0				;pobranie znaku
		int 16h
		mov znak,al
		
		mov dx,offset znak		;wyswietlenie znaku
		mov ah,09
		int 21h
		
		mov al,znak				;zaladowanie znaku do di
		mov di,ax
		and di,000fh			;zamaskowanie starszych 12 bitow
		mov bx,offset liczby	;zaladowanie do bx poczatku tablicy przegladowej "liczby"
		mov ah,[bx+di]			
		mov [si+1],ah			;przeslanie do pamieci mlodszego znaku (na pozycji 2)
		mov ah,24h				
		mov [si+2],ah			;przeslanie $ na pozycje 3 dla przerwania wyswietlania dla int 21h
		
		xor ah,ah
		
		mov al,znak				;ponownie zaladowanie znaku
		mov di,ax
		shr di,1
		shr di,1
		shr di,1
		shr di,1				;przesuniecie o 4 bity w prawo
		and di,000fh			;zamaskowanie starszych 12 bitow
		mov bx,offset liczby	;zaladowanie do bx aresu tablicy przegladowej "liczby" 
		mov ah,[bx+di]
		mov [si],ah				;zaladowanie do pamieci wartosci znaku (na pozycje 1)
		
		mov dx,offset clr		;wyswietlenie odh i oah
		mov ah,09
		int 21h
		
		mov dx,offset napis2	;wyswietlenie napis2
		mov ah,09
		int 21h
		
		mov dx,si				;wyswietlenie wartosci podanego wczesniej znaku
		mov ah,09
		int 21h
		
		mov ah,4ch
		int 21h
			
	.exit
end

Wszystko działa tak jak powinno. Z ciekawości zrobiłem mała modyfikację tego programu, a mianowicie zamieniłem rejestry DI i SI
między soba. Po zmianie kod wygląda tak

.model tiny
.data
      liczby db "0123456789ABCDEF"
   	  znak db ?,'$'
   	  napis1 db 'Podaj znak: $'
   	  napis2 db 'Podany znak ma wartosc: $'
   	  clr db 13,10,'$'
.code  	  
	.startup
	
		mov dx,offset napis1	;wyswietlenie napisu 'podaj znak'
		mov ah,09
		int 21h
		
		mov ah,0				;pobranie znaku
		int 16h
		mov znak,al
		
		mov dx,offset znak		;wyswietlenie znaku
		mov ah,09
		int 21h
		

		mov al,znak			
		mov si,ax
		and si,000fh			;zamaskowanie starszych 12 bitow
		mov bx,offset liczby		;zaladowanie poczatku tablicy "liczby"
		mov ah,[bx+si]
	
		mov [di+1],ah			;przeslanie do pamieci "mlodszej" cyfry (na pozycji nr 2)
		mov ah,24h			;zaladowanie do pamieci $ na 3 pozycje dla przerwania wyswietlania dla int 21h
		mov [di+2],ah
		
		xor ah,ah				
		
		mov al,znak				;zaladowanie ponownie znaku 
		mov si,ax
		shr si,1
		shr si,1
		shr si,1
		shr si,1                               ;przesuniecie aby uzyskac starsze 4 bity
		and si,000fh			;zamaskowanie pozostalych starszych 12 bitow
		mov bx,offset liczby
		mov ah,[bx+si]
		mov [di],ah
		
		mov dx,offset clr		;wyswietlenie 0dh i 0ah
		mov ah,09
		int 21h
		
		mov dx,offset napis2	;wyswietlenie drugiego napisu
		mov ah,09
		int 21h
		
		mov dx,di				;wyswietlenie wartosci podanego znaku
		mov ah,09
		int 21h
		
		mov ah,4ch
		int 21h
				
	.exit
end

W tym momencie wyświetlenie wartości znaku (mimo podania na pozycji [si+2] znaku $) nie kończy się tylko na samej wartości
ale zbiera z pamięci następne bajty i wyświetla je.
Oba programy sprawdziłem debugerami i w obu działanie jest identyczne (tylko DI i SI są zamienione).
Wpisanie na początku MOV DI,SI rozwiązuje problem
Tylko dlaczego tak się dzieje.....
Pewnie czegoś nie wiem, nie doczytałem (wiem że rejestr SI troche się różni od rejestru DI ale chyba w tak prostym programie nie powinno to mieć znaczenia), ogólnie tkwie w jakimś błednym myśleniu i mam nadzieje że ktoś mnie z tego wyprowadzi. Proszę o jakąś podpowiedź...

0

Oba programy mają ten sam błąd: inicjalizujesz tylko jeden rejestr (w pierwszym programie di) a drugiego nie (w pierwszym programie si).

Dlatego jeden z rejestrów zawiera śmieci i wskazuje nie wiadomo nawet gdzie.
to że jeden program działa a drugi nie to przypadek – polegasz na niezdefiniowanym zachowaniu.

0
l00c napisał(a):

Jeśli chodzi o programowanie to jestem całkowitym amatorem, tak więc prośba o wyrozumiałość. :)`
....
<code=asm>

Zacznij od języka wyższego poziomu. Za assemblera bierz się dopiero, gdy nie będziesz już "całkowitym amatorem" (wystarczy jak pozbędziesz się słowa "całkowitym").
W asemblerze trzeba pamiętać o tonie różnych problemów, co ostatecznie doprowadzi cię do zniechęcającej irytacji.

0

Dzięki za podpowiedzi.
A co do tego "całkowity amator" to troche przesadziłem. Kiedyś w szkole bawiłem się asemblerem na 8085 i 8051 z całkiem niezłym skutkiem (zabawy z diodami, wyświetlaczami), i troche Turbo Pascala liznąłem. Ogólną "filozofie" asemblera znam i wiem że na sporo rzeczy trzeba uważać. na razie jeszcze troche spróbuje wejść w to bardziej, jak się gdzieś zablokuje to wtedy pomyśle nad ponownym startem od czegoś prostszego.

Jeszcze pytanie do Azarien. Ale jeśli nie zainicjalizowałem ale wysłałem dane pod [si],[si+1],[si+2] (pod [si+2] jest $) a poźniej startuje z wyświetlaniem od [si] to nawet jeśli nie wiadomo gdzie to się znajduje to powinno chyba przejść. Chyba że coś w między czasie modyfikuje rejest SI.

Pozdrawiam

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