[Assembler] Program dla procesora 8086

Witam

Na studiach piszemy program w assemblerze dla procesora intel 8086, który jak wiadomo jest emulowany w dzisiejszych procesorach. Mniejsza z tym.

Więc mam do napisania program:

  1. Program pobiera ciąg 5 znaków.

  2. Te znaki zostają sprawdzone pod kątem czy są to cyfry w przedziale od 0 do 9.

  3. Jeśli okazuje się to liczba wpisujemy ją do zmiennej “suma” typu “dw” w segmencie danych.

Oto mój program:

DosIntr	equ	21h

RetToDos	equ	4Ch

OK equ	0h


Progr segment

		assume	cs:Progr,ds:dane,ss:stosik

Start:	mov ax,dane

		mov ds,ax

		mov ax,stosik

		mov ss,ax

		mov sp,offset szczyt

--------------------------------------------------- powyższy fragment dostaliśmy jako szablon

		lea dx,tekst    

		mov ah,9 // Wyświetlenie prośby o wpisanie liczby z przedziału 0 do 65535

		int DosIntr	


		lea dx,dlbuf	

		mov ah,0Ah // wczytanie znaków do łańcucha znaki

		int 21h


		lea dx,enterr	

		mov ah,9 // linia przerwy

		int DosIntr


		CMP ile,0 // jak nic nie zostało wpisane to komentarz o braku liczby

		JE komentarz1


		xor ch,ch	

		xor ax,ax // wyczyszczenie rejestrów CH oraz AX i przeniesienie do rejestru CL informacji o ilości wprowadzonych znaków

		mov cl,ile

		sub cl,'1'




Ppetli:	mov SI,krok                  

		mov al,znaki[SI]           

		sub al,'0'                         

                mov ah,al                        

                mov sub ah,10

                JNC komentarz2

		add bx,ax

		JC komentarz3 

		CMP krok,cx

		JE komentarz4

		INC krok

		mul bx;mnoznik

		JMP Ppetli



komentarz1:	mov dx,offset tekst1

		        mov ah,9

		        int DosIntr

		        jmp koniec

komentarz2:	mov dx,offset tekst2

		        mov ah,9

		        int DosIntr

		        jmp koniec

komentarz3:	mov suma,bx

		        mov dx,offset tekst3

		        mov ah,9

		        int DosIntr

		        jmp koniec

komentarz4:	mov dx,offset tekst4

		        mov ah,9

		        int DosIntr

		        jmp koniec


koniec: mov ah,RetToDos

		        mov al,OK

		        int DosIntr

Progr ends


dane segment

dlbuf db 6

ile db 0

znaki db 7 dup ("$")

mnoznik db '10'

lancuch db '0123456789ABCDEF'

tekst db 'Prosze wpisac liczbe w zakresie od "0" do "65535"',10,13,'$'

tekst1 db 'Nic nie zostalo wpisane',10,13,'$'

tekst2 db 'Zle wpisana liczba',10,13,'$'

tekst3 db 'Liczba za duza','$'

tekst4 db 'Mam liczbe','$'

enterr db 10,13,'$'

suma dw 0

krok dw 0

dane ends


stosik segment

		        dw 100h dup(0)

szczyt label word

stosik ends

Algorytm został właśnie w taki sposób wypisany bo został nam nijako narzucony. Więc co nie działa… Sprawdza niby wszystko poprawnie jeśli wprowadzę jeden znak. Gdy wprowadzę więcej to komentarz jest uzależniony od tego czy wprowadzę jako pierwszy znak liczbę czy nie - tak jakby wczytywanie znaków do rejestru al nie przesuwało się (sprawdza tylko 1 znak).

Proszę o pomoc. Gdy pokazałem ten algorytm na zajęciach prowadzący nie zauważył żadnego błędu i nie wie co jest nie tak… jednocześnie to były przed ostatnie zajęcia… na następnych JA to muszę oddać i to JA dostanę ocenę końcową z możliwością zwolnienia egzaminu.

Proszę o wychwycenie tylko i wyłącznie tego błędu.

Masz taki fragment kodu:

mov cl,ile

sub cl,'1'

a później porównywane jest:

CMP krok,cx

JE komentarz4

Rozumiem, że założenie było takie, żeby odjąć od liczby wczytanych znaków liczbę 1, a potem porównywać krok z wartością rejestru cx. Jednak po wykonaniu odejmowania sub cl,‘1’ nie odejmiemy jedynki, tylko wartość kodu ASCII liczby 1, czyli 49.

bx, nigdzie nie jest zerowane

sub al,‘0’

mov ah,al

mov sub ah,10

JNC komentarz2

nie sprawdza czy to nie jest znak mniejszy ‘0’

add bx,ax

do bx doda się (257*X-2560) gdzie X wpisana cyfra, chyba nie o to chodziło.

mul bx

do dx,ax wpiszę się ax*bx - dalej wynik jest ignorowany

kiedy wypisujesz że masz liczbę to jej nie masz

kiedy stwierdzasz ze liczba jest za duża to do zmiennej Suma wpisujesz bx - nie wiedzieć poco.

wziąłem wasze rady do serca, przeczytałem trochę więcej o mnożeniu (MUL) i poprawiłem kod (przepraszam za niektóre bezsensowne elementy, ale to już były moje akty desperacji). Teraz mi elegancko przelatuje przez kod, ale jednocześnie nie mogę znaleźć elementu który mam poprawić jeśli chodzi o sprawdzenie przepełnienia (większej liczby niż 65535). Proszę o wskazówki.

DosIntr equ	21h

RetToDos	equ	4Ch

OK equ	0h


Progr segment

		assume	cs:Progr,ds:dane,ss:stosik

Start: mov ax,dane

		mov ds,ax

		mov ax,stosik

		mov ss,ax

		mov sp,offset szczyt


		lea dx,tekst    

		mov ah,9

		int DosIntr	


		lea dx,dlbuf	

		mov ah,0Ah

		int 21h


		lea dx,enterr	

		mov ah,9

		int DosIntr


		CMP ile,0	

		JE komentarz1

		xor ch,ch	

		xor ax,ax

		xor bx,bx

		mov cl,ile

		sub cl,1





Ppetli: xor ax,ax

		mov SI,krok

		mov al,znaki[SI]

		sub al,'0'

		CMP al,10

		JNC komentarz2

		xor ah,ah

		xor bh,bh

		add bl,al

		CMP bh,0

		JNE komentarz3 

		CMP krok,cx

		JE komentarz4

		INC krok

		xor ax,ax

		mov al,mnoznik

		mul bl

		mov bl,al

		JMP Ppetli



komentarz1:	mov dx,offset tekst1

		mov ah,9

		int DosIntr

		jmp koniec

komentarz2:	mov dx,offset tekst2

		mov ah,9

		int DosIntr

		jmp koniec

komentarz3:	mov dx,offset tekst3

		mov ah,9

		int DosIntr

		jmp koniec

komentarz4:	mov suma,bl

		mov dx,offset tekst4

		mov ah,9

		int DosIntr

		jmp koniec






koniec: mov ah,RetToDos

		mov al,OK

		int DosIntr

Progr ends





dane segment

dlbuf db 6

ile db 0

znaki db 7 dup ("$")

mnoznik db '10'

lancuch db '0123456789ABCDEF'

tekst db 'Prosze wpisac liczbe w zakresie od "0" do "65535"',10,13,'$'

tekst1 db 'Nic nie zostalo wpisane',10,13,'$'

tekst2 db 'Zle wpisana liczba',10,13,'$'

tekst3 db 'Liczba za duza','$'

tekst4 db 'Mam liczbe','$'

enterr db 10,13,'$'

suma db 0

krok dw 0

dane ends


stosik segment

		dw 100h dup(0)

szczyt label word

stosik ends

		end start

mnożnik ma być 10 a u cienie mnożnik 49 (‘1’ - pierwszy znak z ‘10’), ma być:

mnożnik db 10

częściowo miałeś sprawdzenie przepelnienia ale go sknociłeś, było prawie dobrze:

add bx,ax

JC komentarz3

z tym że nie to dodawałeś i brakuje podobnego sprawdzenia po mnożeniu przez 10.

Miałeś sprawdzenie czy znak nie jest mniejszy niż ‘0’, ale brakowało sprawdzenia czy nie jest większy niż ‘9’.

Teraz masz sprawdzenie czy nie jest większy niż ‘9’. ale brakuje sprawdzenia czy nie jest mniejszy niż ‘0’.

Dziękuję za rady:) Program poprawiony robi to co ma robić… tzn prawie:P To jest pierwsza część zadania teraz wpisaną liczbę muszę wypisać w postaci heksadecymalnej i binarnej… ale już powinienem sobie poradzić;)

Dodane piątek, 15 stycznia 2010, 23:27

No i mam ostatnią prośbę jeśli chodzi o ten program… Przyjmuje mi liczby, przerabiam je na system binarny i heksadecymalny - pełen sukces… prawie. Posiadam coś takiego:

DosIntr equ	21h

RetToDos	equ	4Ch

OK equ	0h



dalej: mov SI,0

		xor cx,cx

		mov ax,bx

		mov cx,2

binarny: xor dx,dx

		div cx

		ADD dx,'0'

		mov bin[SI],dx

		CMP ax,1

		JL dalejhex

		INC SI

		JMP binarny


dalejhex:	mov SI,4

		xor cx,cx

		mov ax,bx

		mov cx,16

hex: xor dx,dx

		div cx

		CMP dx,9

		JA szesnastka

		ADD dx,'0'

		mov hexa[SI],dx

		CMP ax,1

		JL komentarz4

		INC SI

		JMP hex

szesnastka:

		SUB dx,10

		ADD dx,'A'

		mov hexa[SI],dx

		CMP ax,1

		JL komentarz4

		INC SI

		JMP hex



Progr ends




znaki db 7 dup ("$")

bin dw 16 dup (),'$'

hexa dw 5 dup(),'$'

Podczas przeliczania na systemy binarne i heksadecymalne mam ustawione by SI było ustawione na “0” i aby z kolejnym ruchem pętli zwiększało się o jeden - i jest wszystko ok, zapisywane super tylko że liczba od tyłu. Jeśli ustawie SI odpowiednio na 16 i na 4 i będę zmniejszał SI o jeden to wprawdzie zapisuje od tyłu, ale w końcowym efekcie wyświetlane są ostatnie wyniki operacji przypisu… reszty jakby nie było…

Czemu się tak dzieje? I gdzie mam w takim razie błąd…?;/

Dodane sobota, 16 stycznia 2010, 15:08

Problem rozwiązany - zamiana w odpowiednim miejscu rejestru DX na DL, a typ łańcuchów z dw na db