Greetings to everyone, as this is my first post.
I need a little help from those more experienced than myself. I've been trying to write a program which converts a matrix of decimal numbers stored in a file to a matrix of hex,octal or binary numbers, depending on a flag entered on input. The new matrix is to be written to a separate file. Names of the files should be entered and the flag should be taken from the command line. Example:
calling
macierze.exe inmatrix b outmatrix
if inmatrix looks like this
1 2 3
4 5 6
7 8 9
it should be converted to
00000001 00000010 00000011
00000100 00000101 00000110
00000111 00001000 00001001
the above should be written to the outmatrix file.
The numbers are from the range 0-255.
I thought I had it down when I wrote the code, but what I get in the outmatrix is a line:
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
This happens with all conversions (the oct conversion writes zeros in groups of three and the hex conversion writes zeros in pairs). What I ask is why? Please note that I don't want a "write this..." kind of answer, but rather one that tells me what is wrong, why and how it should be corrected. This program has other problems as well, but I'm going to deal with them myself (at least I think I can), so please refer just to the conversion.
code1 segment ; SEGMENT KODU
start: mov ax,seg stos1 ; ustawienie wskaznikow do
mov ss,ax ; segmentu stosu
mov sp,offset top1 ; oraz jego szczytu
mov ax, seg dane1 ; ustawienie segmentu danych
mov ds,ax
mov ah,62h ; funkcja wrzucajaca do bx dlugosc i zawartosc linii komend
int 21h ; przerwanie
mov es,bx ; skopiowanie linii komend do es
mov al,es:[80h] ; w 80h jest dlugosc linii komend (nie liczac koncowego entera)
cmp al,5 ; jesli linia komend byla krotsza niz 5 znakow
jl arg_err ; to wywolanie nastapilo z blednymi argumentami (2 nazwy plikow, 2 spacje i 4 znaki na kod to co najmniej 8 znakow)
xor ah,ah ; ah=0
mov cx,ax ; cx = dlugosc linii polecen
mov byte ptr ds:[lp_dlug], al ; zapisanie dlugosci linii polecen do zmiennej
xor si,si ; si=0
; PRZEPISANIE LINII POLECEN
czytaj_lp:
mov ah, es:[82h + si] ; przenies kolejny znak lini polecen do ah (81h to spacja)
mov byte ptr ds:[lp_wart + si],ah ; a z ah przenies do odpowiedniego bajtu zmiennej lp_wart (przechowujacej linie polecen)
inc si ; zwieksz si o jeden (kolejny znak)
loop czytaj_lp ; powtarzaj az cx==0 (kolejno znaki z lini polecen)
; tutaj si = dlugosc linii polecen
; PARSOWANIE LINI POLECEN
mov bx,si ; bx = dlugosc linii polecen
xor si,si ; si=0, posluzy za indeks kolejnego znaku w linii polecen
xor di,di ; di=0, bedzie indeksem kolejnego znaku w aktualnie pobieranym parametrze
parsuj_in:
cmp byte ptr ds:[lp_wart + si],' ' ; jesli napotkano spacje
je zakoncz_in ; zakoncz pobieranie pierwszego argumentu (nazwy pliku wejsciowego)
mov al,byte ptr ds:[lp_wart + si] ; w innym wypadku zapisz biezacy znak do al
mov byte ptr ds:[pl_in + di],al ; a z al zapisz go do kolejnego bajtu pl_in (sciezka do pliku wejsciowego)
inc si ; si+=1 (kolejny znak w lini polecen)
inc di ; di+=1 (kolejny znak w zmiennej pl_in)
cmp si,bx ; jesli to koniec linii polecen
je arg_err ; to wywolano program z tylko jednym argumentem, co jest bledem wywolania
jmp parsuj_in ; powtorz powyzsze operacje dla kolejnego znaku
zakoncz_in:
mov byte ptr ds:[pl_in + di],0 ; na koniec zmiennej z nazwa pliku wejsciowego wpisz 0 (koniecznosc dla nazw plikow)
inc si ; przejdz do kolejnego znaku linii polecen
xor di,di ; di=0, kolejny argument
parsuj_flage:
cmp byte ptr ds:[lp_wart+si],' '
je zakoncz_flage
mov al, byte ptr ds:[lp_wart+si]
cmp al, 'h'
je wpisz
cmp al, 'o'
je wpisz
cmp al, 'b'
jne flag_err
wpisz:
mov byte ptr ds:[flaga], al
inc si
zakoncz_flage:
cmp byte ptr ds:[lp_wart+si],' '
jne flag_err
inc si
parsuj_out:
cmp byte ptr ds:[lp_wart + si],' ' ;jezeli trafilo na spacje to podano za duzo argumentow - blad
je arg_err ;przeskocz to obslugi bledu argumentow
mov al,byte ptr ds:[lp_wart + si] ;zapisz do al aktualny znak
mov byte ptr ds:[pl_out + di],al ;i wpisz go do zmiannej pl_out (sciezka do pliku wynikowego)
inc si ;zwieksz si o 1 (kolejny znak w lini polecen)
inc di ;zwieksz di o 1 (kolejny znak w zmiennej pl_out
cmp si,bx ;jezeli doszedlem do ostatniego znaku lini polecen
je zakoncz_out ;to zakonczono linie polecen, przejdz dalej
jmp parsuj_out ;zrob to co powyzej dla kolejnego znaku
zakoncz_out:
mov byte ptr ds:[pl_out + di -1],0 ;zapisz 0 na koniec sciezki do pliku wyjscia
cmp byte ptr ds:[pl_out],0 ;jezeli pl_out znaczyna sie od 0 to ze zamist pl_out wpisano spacje
je arg_err ;blad skladni
xor ax, ax ; zeruje wszystkie dotad uzywane rejestry
xor di,di
xor si,si
xor bx, bx
; OTWIERANIE PLIKOW
mov dx,offset ds:[pl_in] ;do dx wpisujemy sciezke do pliku wejsciowego zakonczona zerem
mov al,0 ;do al wpisujemy tryb dostepu do pliku 0 = do odczytu
mov ah,3dh ;do ah numer funkcji 3Dh - otworz plik
int 21h ;przerwanie DOS (otwieramy plik
jc plik_err ;jezeli nie otwirzono pliku to przeskocz do obslugi bledu
mov word ptr ds:[fp_in],ax ;wpisz do zmiennej fp_in uchwyt do pliku z danymi do szyfrowania
mov dx,offset ds:[pl_out] ;do dx wpisz sciezke do pliku wynikowego
mov cx,0 ;w cl trzymamy atrybuty pliku. 0 = bez atrybutow
mov al,1 ;otworz w trybie do zapisu
mov ah,3ch ; otworz plik ;funkcja 3Ch - utworz plik (istniejacy obetnij do zera)
int 21h ;wywolanie przerwania DOS
jc plik_err ;jezeli sie nie udalo to blad
mov word ptr ds:[fp_out],ax ;do zmiennej fp_out wpisz uchwyt do pliku wynikowego
; TEST TEST TEST ZAPISYWANIA
; push cx
; mov cx, 1
; mov dx,offset ds:[buf_out]
; mov bx,word ptr ds:[fp_out]
; mov ah,40h
; int 21h
; pop cx
;
; mov ax, 0e31h
; int 10h
; KONWERSJA MACIERZY
mov byte ptr ds:[linia],1
mov byte ptr ds:[kolumny],0
mov byte ptr ds:[kolumny],0
petla_konwersji:
call czytajzpliku
cmp ax,0
je sprawdz_ostatni
mov cx, ax
xor di,di
xor si,si
nast_liczba:
mov al,byte ptr ds:[buf_in+si]
; mov ah, 0eh
; int 10h
cmp al,' '
je next
cmp al,' '
je next
cmp al,10 ;10=Line feed
je koniec_wiersza
cmp al,13 ;13=Carriage return
je next
cmp al, '0'
jb data_err
cmp al, '9'
ja data_err
czyt_liczbe:
inc di
cmp di, 3
jg data_err
mov ah, byte ptr ds:[liczba+1]
mov byte ptr ds:[liczba], ah
mov ah, byte ptr ds:[liczba+2]
mov byte ptr ds:[liczba+1], ah
mov byte ptr ds:[liczba+2], al
inc si
cmp si, cx
je koniec_bufora
mov al, byte ptr ds:[buf_in+si]
cmp al, ' '
je koniec_liczby
cmp al, ' '
je koniec_liczby
cmp al, 10
je koniec_liczby
jmp czyt_liczbe
koniec_bufora:
call czytajzpliku
mov cx,ax
cmp ax,0
jne czyt_liczbe
koniec_liczby:
mov byte ptr ds:[ostatniznak], al
mov ah, byte ptr ds:[kolumny_biez]
inc ah
mov byte ptr ds:[kolumny_biez], ah
xor di, di
call sprawdz_zakres
; mov dx, offset ds:[liczba]
; mov ah,9h ;jak wyzej, komunikat o bledzie pliku
; int 21h
to_bin:
xor ax, ax
mov ah, byte ptr ds:[liczba]
add al, ah
sub al, '0'
mov dl, 10
mul dl
mov ah, byte ptr ds:[liczba+1]
add al, ah
sub al, '0'
mul dl
mov ah, byte ptr ds:[liczba+2]
add al, ah
sub al, '0'
wybor_konwersji:
cmp byte ptr ds:[flaga], 'h'
je hexconv
cmp byte ptr ds:[flaga], 'o'
je octconv
push cx
mov cx, 8
binconv:
mov byte ptr ds:[buf_out], 30h
shl al,1
adc byte ptr ds:[buf_out],0
call zapisz
loop binconv
jmp po_konwersji
hexconv:
push cx
mov cx,2
hexconv_loop:
xor bl,bl
shl al,1
adc bl,0
shl bl,1
shl al,1
adc bl,0
shl bl,1
shl al,1
adc bl,0
shl bl,1
shl al,1
adc bl,0
cmp bl, 9
jg morethan9
add bl,'0'
mov byte ptr ds:[buf_out], bl
call zapisz
jmp endhex
morethan9:
sub bl,10
add bl,'A'
mov byte ptr ds:[buf_out],bl
call zapisz
endhex:
loop hexconv_loop
jmp po_konwersji
octconv:
push cx
mov cx,2
xor bx,bx
shl al,1
adc bl,0
shl bl,1
shl al,1
adc bl,0
add bl,'0'
mov byte ptr ds:[buf_out], bl
call zapisz
octconv_loop:
xor bx,bx
shl al,1
adc bl,0
shl bl,1
shl al,1
adc bl,0
shl bl,1
shl al,1
adc bl,0
add bl,'0'
mov byte ptr ds:[buf_out],bl
call zapisz
loop octconv_loop
jmp po_konwersji
po_konwersji:
mov byte ptr ds:[buf_out], ' '
call zapisz
pop cx
mov byte ptr ds:[liczba], '0'
mov byte ptr ds:[liczba+1], '0'
mov byte ptr ds:[liczba+2], '0'
cmp byte ptr ds:[ostatniznak],10
je koniec_wiersza
jmp next
koniec_wiersza:
cmp byte ptr ds:[linia], 1
jne nastepnywiersz
mov al, byte ptr ds:[kolumny_biez]
mov byte ptr ds:[kolumny], al
mov byte ptr ds:[kolumny_biez], 0
mov byte ptr ds:[buf_out],10
call zapisz
jmp next
nastepnywiersz:
mov al, byte ptr ds:[linia]
inc al
mov byte ptr ds:[linia], al
mov al, byte ptr ds:[kolumny_biez]
cmp al, 0
je next
cmp byte ptr ds:[kolumny], al
jne data_err
mov byte ptr ds:[kolumny_biez], 0
mov byte ptr ds:[buf_out],10
call zapisz
next:
inc si
cmp si, cx
je petla_konwersji
jmp nast_liczba
sprawdz_ostatni:
mov al, byte ptr ds:[kolumny_biez]
cmp al, 0
je zamknij
cmp byte ptr ds:[kolumny], al
jne data_err
jmp zamknij
zamknij:
mov bx,word ptr ds:[fp_in] ;do bx wpisz uchwyt do pliku wejsciowego
mov ah,3eh ;funkcja 3Eh - zamknij plik
int 21h ;wywolanie przerwania DOSa
mov bx,word ptr ds:[fp_out]
mov ah,3eh ; to samo dla pliku wyjsciowego
int 21h
koniec: mov ah,4ch ;funkcja przerwania 4Ch - zakoncz program i wroc do DOS
mov al,0 ;wartosc zwracana do DOS przez program (kod wyjscia)
int 21h ;przerwanie DOSa
; KOMUNIKATY BLEDOW
arg_err:
mov dx,offset ds:[blad_a] ;wpisz do dx adres zmiennej z tekstem z informacja o bledzie argumentow
mov ah,9h ;funkcja przerwania 21h - wypisz na ekran
int 21h ;przerwanie DOSa
jmp koniec ;zakoncz program
plik_err:
mov dx,offset ds:[blad_p]
mov ah,9h ;jak wyzej ale komunikat o bledzie pliku
int 21h
jmp koniec
flag_err:
mov dx, offset ds:[blad_f] ; komunikat o blednym kluczu
mov ah,9h
int 21h
jmp koniec
data_err:
mov dx, offset ds:[blad_d] ; komunikat o blednych danych
mov ah,9h
int 21h
jmp zamknij
sprawdz_zakres proc
cmp byte ptr ds:[liczba],'2'
jg data_err
jne good
cmp byte ptr ds:[liczba+1],'5'
jg data_err
jne good
cmp byte ptr ds:[liczba+2],'5'
jg data_err
good:
ret
sprawdz_zakres endp
czytajzpliku proc
mov dx, offset ds:[buf_in]
mov cx, word ptr ds:[buf_roz]
mov bx, word ptr ds:[fp_in]
mov ah, 3fh
int 21h
xor si,si
ret
czytajzpliku endp
zapisz proc
push ax
push cx
mov cx,1
mov dx, offset ds:[buf_out]
mov bx, word ptr ds:[fp_out]
mov ah, 40h
int 21h
pop cx
pop ax
ret
zapisz endp
code1 ends
; KONIEC SEGMENTU KODU
; SEGMENT DANYCH
dane1 SEGMENT
blad_p db "Nie mozna otworzyc pliku $" ;komunikat o bledzie pliku
blad_a db "Podaj 3 argumenty: plik_wejsciowy flaga(h/o/b) plik_wyjsciowy $" ;komunikat o blednej skladni wywolania prog.
blad_f db "Nieprawidlowa flaga $" ;komunikat o niepoprawnosci klucza
blad_d db "Plik zawiera niepoprawne dane $"
lp_dlug db ? ;dlugosc lini polecen
lp_wart db 128 dup(?) ;linia polecen
pl_in db 128 dup(?) ;sciezka do pliku wejsciowego
pl_out db 128 dup(?) ;sciezka do pliku wyjsciowego
fp_in dw ? ;uchwyt do pliku z danymi
fp_out dw ? ;uchwyt do pliku wynikowego
buf_roz dw 512 ;rozmiar bufora odczytu z pliku do zaszyforowania
buf_in db 512 dup(?) ;bufor odczytu z pliku do zaszyfrowania
flaga db ?
liczba db 3 dup('0')
ostatniznak db ?
kolumny db ?
kolumny_biez db ?
linia db ?
buf_out db ?
dane1 ENDS
; KONIEC SEGMENTU DANYCH
; SEGMENT STOSU
stos1 segment STACK
dw 250 dup(?)
top1 dw ?
stos1 ends
end start
Thank you in advance and sorry for the really long post.
Hi samyazza,
You should mention what you are using to assemble your code.
I got 55 severe errors using MASM. Anyway, running it in DEBUG
shows that at the following;
; the source of my sorrow
binconv:
xor bx,bx ; bx=0
add bl, 30h ; bl='0'
shl al, 1 ; al shifted left, I think the lost bit should bo to carry flag, but apparently it doesn't
adc bl, 0 ; because this always gives zero :(
mov byte ptr ds:[buf_out], bl ; so a zero is always moved here
call zapisz ; and this procedure (writes the byte at buf_out to file) always writes a zero :/
loop binconv
You are not preserving AL in zapisz. So everthing after the
first call is incorrect.
HTH,
Steve N.
It's
QuoteMicrosoft (R) Macro Assembler Version 6.13.7299
It compiles fine with that assembler.
Anyway I was sure that since I move 40h to the AH register inside that procedure, AL will be left unmoved. Could you tell me which instruction is the one modifying it?
edit: okay, that was a stupid question, since there is only one interrupt in the procedure XD
Thank you very much for your help! I'd probably be stuck on it for heaps of time ;)
One small point, when the program receives control DS and ES are set to the segment address of the PSP.
QuoteMicrosoft (R) Macro Assembler Version 6.13.7299
It compiles fine with that assembler.
Okay, thanks. Time for some experimenting with
different versions...
Regards,
Steve N.
Right, I have corrected the problem I asked about earlier. I've also corrected an issue with writing line feeds to the outfile. I'm still puzzled about one issue though, so once again I ask for your help.
If the infile contains an improper matrix, e.g.
1 2 3
4 5 6 7
8 9 0
...my program should throw a data_err. It converts everything though no matter what the inmatrix looks like. It must be an issue with updating the appropriate variables:
-linie - this one is supposed to say which line we're in
-kolumny - this should remember the amount of columns in line one
-kolumny_biez - this should keep track of how many columns we've got in the current line.
At the end of each line a jump to the section "koniec_wiersza " should be performed. In that section I wanted to achieve the following - check if we're in line one, if so - remember the amount of columns (from kolumny_biez to kolumny); if not: if there were no numbers in this line, carry on (a line with only a line feed is to be ignored), else compare the amount of numbers in the current row with the amount of numbers in the first row (remembered in 'kolumny') and if they are not equal, go to data_err.
This doesn't work though. For no instance of a wrong matrix is a data_err thrown. If someone could check out why, I'd be ever grateful. The code above has been updated.
If you have not, (logically) outline your proc on a higher level,
C...C++, then fine tune it with masm.
If thats still too low, do use pseudocode,
then tune it.
http://en.wikipedia.org/wiki/Pseudocode
Quote from: samyazza on November 30, 2008, 12:20:26 PM
; KONWERSJA MACIERZY
mov byte ptr ds:[linia],1
mov byte ptr ds:[kolumny],0
mov byte ptr ds:[kolumny],0
Did you really mean to twice set 'kolumny'? or maybe one of them you meant 'kolumny_biez'?