Writing a binary, hex or octal digit to a file

Started by samyazza, November 30, 2008, 12:20:26 PM

Previous topic - Next topic

samyazza

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.

FORTRANS

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.

samyazza

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 ;)

MichaelW

One small point, when the program receives control DS and ES are set to the segment address of the PSP.
eschew obfuscation

FORTRANS

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.

samyazza

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.

askm


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

old programmer

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'?