Skip to content

Instantly share code, notes, and snippets.

@P4
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save P4/9771311 to your computer and use it in GitHub Desktop.
Save P4/9771311 to your computer and use it in GitHub Desktop.
; Parser Argumentow
; by Pawel Maniecki
; Asemblery, IET AGH
.186 ; pusha, popa
_Dane segment
; Struktura przechowujaca argumenty
argc db 0 ; ilosc argumentow ( dlugosc args )
args dw 10h dup(?) ; offsety na poczatki argumentow w argv
argv db 80h dup('$') ; wartosci argumentow rozdz $
_Dane ends
; MAKRO: Jump if Equal -- jesli Reg ma wartosc Val, skocz do Label
jmpEq macro Reg, Val, Label
cmp Reg, Val
je Label
endm
_Kod segment
start: ; DS (oraz ES) zawiera adres PSP -- Program Segment Prefix
; Inicjowanie stosu
mov ax, seg wstosu ; dla rejestrow segmentowych
mov ss, ax ; mov tylko z rejestrem/pamiecia, nie wartoscia
mov sp, offset wstosu
; Wczytanie argumentow
call ParseArgs ; wypelnia (argc,args,argv) argumentami z DS:[80h]
; Wypisanie:
mov ax, seg argv
mov ds, ax ; ds na segment danych
call GetArgNum ; ax <= ilosc argumentow
mov cx, ax
jmpEq cx, 0, quit ; nie iteruj gdy cx=0 (overflow przy loop)
mov dx, 0 ; DL na zerowy argument
L1:
push cx
push dx
call GetArgPos ; nr w DL, wynik w AX
mov dx, ax ; DX <= adres obecnego argumentu
mov ah, 9 ; wypisz ds:dx
int 21h
mov ah, 2 ; pisz znak z dl
mov dl, 0Dh ; \r
int 21h
mov dl, 0Ah ; \n
int 21h
pop dx
inc dl ; DL++, na nastepny arg
pop cx
loop L1 ; CX--
quit:
mov ah, 4Ch
int 21h
; ** PROCEDURY **
; ParseArgs -------------------------------------------------
; wczytaj argumenty z [80h] do struktury (argc,args,argv)
; wykorzystujac EatWS i CopyWord.
; przy wywolaniu rejestr DS powinien wskazywac na segment PSP
ParseArgs proc
pusha ; push AX, CX, DX, BX, SP, BP, SI, DI
mov cx, 0 ;
mov cl, byte ptr ds:[80h] ; cx na ilosc bajtow lini komend
mov si, 81h ; ds:[si] na poczatek bufora argumentow w PSP
mov ax, seg argv ;
mov es, ax ; es na segment danych
mov di, offset argv ; es:[di] na poczatek argv
iter:
jmpEq cx, 0, return ; Wyjdz gdy bufor sie skonczyl
call EatWS ; zmniejsz cx, zwieksz si
jmpEq cx, 0, return ; Bufor zawieral same biale znaki
; dodaj nowy parametr do args
mov bx, 0
mov bl, byte ptr es:[argc] ; bx na il. argumentow
shl bx, 1 ; bx *= 2, adresujemy word
mov word ptr es:[args+bx], di ; aktualne di jako adr tego parametru
inc byte ptr es:[argc] ; argc++
call CopyWord ; zmniejsz cx, zwieksz si+di
jmp iter
return:
popa ; odwrotnie do PUSHA, nie kopiuje SP, pomija go
ret
ParseArgs endp
; Eat WhiteSpace -------------------------
; przesun SI na pierwszy niebialy bajt
; zmienia: si, cx
EatWS proc
push ax
iter: ; wyjdz gdy bufor sie skonczyl
jmpEq cx, 0, return ; while ( cx > 0 )
dec cx ; cx--
lodsb ; al = ds:[si] ; si++
; if ( bialy ) continue
jmpEq al, 20h, iter ; spacja
jmpEq al, 09h, iter ; \t tab
jmpEq al, 0Ah, iter ; \n line-feed
jmpEq al, 0Ch, iter ; \f form-feed
jmpEq al, 0Dh, iter ; \r carriage-return
; gdy niebialy:
inc cx ; "oddajemy" pobrany znak,
dec si ; cofajac sie w buforze
return:
pop ax
ret
EatWS endp
; CopyWord --------------------------------------------------------
; kopiuj bajty z ds:[si] do es:[di], az do pierwszego bialego znaku
; przesun SI na pierwszy bialy, DI na miejsce na kolejny argument
; zmienia: si, di, cx
CopyWord proc
push ax
iter: jmpEq cx, 0, return ; wyjdz gdy bufor sie skonczyl
dec cx ; pobranie znaku:
lodsb ; al = ds:[si] ; si++
; if ( bialy ) break
jmpEq al, 20h, done ; spacja
jmpEq al, 09h, done ; \t tab
jmpEq al, 0Ah, done ; \n line-feed
jmpEq al, 0Ch, done ; \f form-feed
jmpEq al, 0Dh, done ; \r carriage-return
; gdy niebialy
stosb ; es:[di] = al, di++
jmp iter
done: ; petla trafila na bialy znak, koryguj indeksy
inc cx ; oddaj pobrany znak
dec si ; wroc w buforze
inc di ; zostaw 1 bajt (dolar) przerwy w argv
return:
pop ax
ret
CopyWord endp
; TODO: czy trzeba pushowac ds, czy lepiej zalozyc ze jest poprawny?
; GetArgNum --------------------
; zaladuj do AL ilosc argumentow
GetArgNum proc
push ds
mov ax, seg argc ; ustaw segment danych
mov ds, ax
mov ax, 0
mov al, byte ptr ds:[argc] ; kopiuj
pop ds
ret
GetArgNum endp
; GetArgPos -----------------------------------
; zaladuj do AX adres argumentu o indeksie z DL
GetArgPos proc
push ds
push bx
mov ax, seg argc ; ustaw segment danych
mov ds, ax
mov ax, 0 ; reset
mov al, dl ; AX = DL
shl ax, 1 ; AX*2, word ptr
mov bx, offset args
add bx, ax ; BX na args[DL]
; AX = adres DL-tego argumentu
mov ax, word ptr ds:[bx]
pop bx
pop ds
ret
GetArgPos endp
; GetArgLen -------------------------------------
; zaladuj do AX dlugosc argumentu o indeksie z DL
GetArgLen proc
push ds
push bx
mov ax, seg args ; ustaw segment danych
mov ds, ax
mov ax, 0 ; reset
mov al, dl ; AX = DL
shl ax, 1 ; AX*2, word ptr
mov bx, offset args
add bx, ax ; BX na args[DL]
; DLugosc jako roznica miedzy adresem obecnego, a kolejnego argumentu
add bx, 2 ; BX na args[DL+1] (2:word)
mov ax, word ptr ds:[bx] ; pobierz adres kolejnego
sub bx, 2 ; powrot na args[DL]
sub ax, word ptr ds:[bx] ; roznica adresow
sub ax, 1 ; uwzglednij dolar przerwy
pop bx
pop ds
GetArgLen endp
_Kod ends
_Stos segment stack
; Rozmiar 80h w slowach (256d bajtow)
dw 7Fh dup(?)
wstosu dw ?
_Stos ends
end start
; Pawel Maniecki
; Asemblery, IET AGH
.186 ; pusha, popa
_Dane segment
; Argumenty
argc db 0 ; ilosc argumentow ( dlugosc args )
args dw 10h dup(?) ; offsety na poczatki argumentow w argv
argv db 80h dup('$') ; wartosci argumentow rozdz $
; Skonwertowane dane wejsciowe
mode db ? ; tryb pracy
key db 16 dup(?) ; 16bajtow / 128bitow skrotu klucza
; Szachownica
board db 153 dup(0) ; 9 wierszy na 17 kolumn
db '$' ;TEST
; Tablica znakow:
; nieodwiedzone, odwiedzone 1-14 razy, pierwszy, ostatni
chars db ' ', ".o+=*BOX@%&#/^", 'S', 'E'
; ** Komunikaty bledow **
emsgANum db "Bledna ilosc argumentow. dopuszczalne tylko 2",'$'
emsgMode db "Bledna wartosc pierwszego argumentu. dozwolone 0 lub 1",'$'
emsgKLen db "Bledna dlugosc klucza. wymagane 32 znaki",'$'
emsgKVal db "Klucz zawiera znaki z poza zakresu [0-9A-F] (wielkie litery)",'$'
_Dane ends
; MAKRO: Jump if Equal -- jesli Reg ma wartosc Val, skocz do Label
jmpEq macro Reg, Val, Label
cmp Reg, Val
je Label
endm
_Kod segment
start: ; DS (oraz ES) zawiera adres PSP -- Program Segment Prefix
; Inicjowanie stosu
mov ax, seg wstosu ; dla rejestrow segmentowych
mov ss, ax ; mov tylko z rejestrem/pamiecia, nie wartoscia
mov sp, offset wstosu
; 1) Wczytanie argumentow
call ParseArgs ; wypelnia (argc,args,argv) argumentami z DS:[80h]
; 2) Weryfikacja i parsowanie danych
; ds na segment danych - wymagane przez GetArg*
mov ax, seg argv
mov ds, ax
; 2.1) Ilosc argumentow
call GetArgNum ; ax <= ilosc argumentow
cmp ax, 2 ; czy 2 argumenty?
jne errorANum ; nie -> blad
; 2.2) Tryb pracy:
mov dl, 0 ; zerowy argument
call GetArgLen ; dlugosc do ax
cmp ax, 1 ; dlugosc 1 bajtu?
jne errorMode ; nie -> blad
call GetArgPos ; adres do ax
mov bx, ax
mov al, byte ptr ds:[bx] ; pobranie warosci argumentu
cmp al, '0' ; znak 0?
je modeOK
cmp al, '1' ; znak 1?
je modeOK
jmp errorMode ; else -> blad
modeOK: ; argument poprawny, zapis w pamieci
sub al, '0' ; konwersja na liczbe
mov bx, offset mode ; ds dalej jest na dx?
mov byte ptr ds:[bx], al ; ustaw mode
; 2.3) Skrot klucza RSA
mov dl, 1
call GetArgLen
cmp ax, 32 ; dlugosc 32 znakow ?
jne errorKeyLen
; 2.3.1) konwersja na bajty:
mov ax, seg key ; przygotowanie do kopiowania danych
mov es, ax ; lancuchowo do ES:DI
mov di, offset key
call GetArgPos ; dl=1, argument z kluczem
mov si, ax ; offset zrodlowy
mov cx, 16 ; po 2 hexy / iteracje
hexLoop:
lodsb ; starszy hex z pamieci
mov ah, al ; starszy do AH
lodsb ; mlodszy do AL
call HexToByte ; konwersja
stosb ; zapis bajtu
loop hexLoop
; 3) Ruchy po planszy:
mov di, offset board ; di+bi -> pole na planszy
mov bx, 76 ; pozycja poczatkowa: pole (4,8)
mov si, offset key ; zrodlo bajtow
mov cx, 16 ; ilosc bajtow
; 3.1) Kolejne bajty:
byteLoop:
push cx
lodsb ; wczytanie bajtu do AL, si++
mov cx,4
; 3.1.1) Kolejne pary bitow:
pairLoop:
cmp byte ptr ds:[di+bx], 14
jae skpinc ; powyzej 14 odwiedzin ten sam znak
inc byte ptr ds:[di+bx] ; ponizej 14 - odwiedz pole
skpinc: call MoveBishop ; przestaw BX, skroc AL o 2 bity
loop pairLoop
pop cx
loop byteLoop
; 3.2) Nadpisz pozycje poczatkowa i koncowa
mov byte ptr ds:[di+76], 15 ; znak 'S'
mov byte ptr ds:[di+bx], 16 ; znak 'E'
; 4) Konwersja na znaki:
mov bx, di ;bx - offset planszy
mov bp, offset chars ;bp - offset znakow
xor di,di ; poczatek planszy
mov cx, 153 ; rozmiar planszy
mov dl, byte ptr ds:[mode] ; tryb pracy: z/bez rotacji
mov dh, 0 ; ilosc rotacji
charLoop:
push cx
mov al, byte ptr ds:[bx+di] ; pobranie ilosci odwiedzin
call PickChar ; konwersja na kod znaku
mov byte ptr ds:[bx+di], al ; zapis znaku w planszy
inc di ; kolejny znak
pop cx
loop charLoop
; 5) Wypisanie na STDOUT
mov si, offset board
mov ah, 2 ; INT 21h :: 02 -> znak na STDOUT
mov cx, 9 ; ilosc rzedow
rowLoop: ; rzedy
push cx
mov cx, 17 ; ilosc kolumn w rzedzie
colLoop: ; kolumny
push cx
lodsb ; znak z planszy do AL, SI++
mov dl, al ; znak do dl, do wypisania
int 21h ; wypisz z DL
pop cx
loop colLoop
; koniec colLoop, wypisz koniec linii
mov dl, 0Ah ; \n
int 21h
mov dl, 0Dh ; \r
int 21h
pop cx
loop rowLoop
; 6) Wyjscie z programu
quit:
mov ah, 4Ch
int 21h
; ** OBSLUGA BLEDOW **
errorANum:
mov dx, offset emsgANum
jmp printErr
errorMode:
mov dx, offset emsgMode
jmp printErr
errorKeyLen:
mov dx, offset emsgKLen
jmp printErr
errorKeyVal:
mov dx, offset emsgKVal
jmp printErr
printErr: ; print error message
mov ax, seg emsgANum ; segment wspolny dla wszystkich
mov ds, ax ; ustaw segment ds na bledy
mov ah, 9 ; wypisanie bledu na ekran
int 21h
mov ah, 4Ch ; wyjscie
int 21h
; ** PROCEDURY **
; PickChar -----
PickChar proc
; (bp wszkazuje na poczatek tablicy znakow)
; (dl zawiera tryb pracy, dh zawiera ilosc wykonanych rotacji)
; (al zawiera wartosc pola)
push si
or dl,dl ; cmp dl, 0
jz direct ; rowne - rotacja wylaczona
cmp al,0 ; nieodwiedzony
je direct
cmp al,15 ; pierwszy
je direct
cmp al,16 ; ostatni
je direct ; wykluczone z rotacji
; MODYFIKACJA -- rotacja tablicy znakow w prawo po kazdym wypisaniu
sub al, dh
jg nofix ; testuj wynik odejmowania
add al, 14 ; niedodatni -> skoryguj dodajac 14
nofix: ; dodatni, wszystko ok
inc dh ; zwkieksz ilosc rotacji
cmp dh, 14 ; wykonano pelen obrot?
jb noreset
sub dh, 14 ; obrot o 14 -> powrot do pozycji poczatkowej
noreset:
direct:; bez rotacji - wartosc == pozycja znaku
xor ah, ah ; mov ah,0 -- AX==AL
mov si, ax ; pozycja znaku do si
mov al, byte ptr ds:[bp+si] ; al = chars[si]
pop si
ret
PickChar endp
; MoveBishop ------
; Przesuwa BX po planszy na podstawie 2 bitow z AL
; po wykonaniu: BX na nowej pozycji, AL skrocony od 2 bajty
MoveBishop proc
pushf
push dx
push cx
; przygotowanie, ustalenie wspolrzednych
mov dl,al ; bo ax uzywany w dzieleniu
mov ax,bx ; wspolrzedne gonca: wsp(w,k) = 17w + k
mov dh,17 ; dzielenie tylko reg, mem, nie immed
div dh ; AX/DH, wynik w AL, reszta w AH => (wiersz, kolumna)
;ruch poziomy:
shr dl,1 ; ustawia CF
jc right
;CF=0, ruch w lewo
cmp ah, 0 ; czy w pierwszej kolumnie?
je vert ; tak -> nie ruszaj sie
dec bx ; nie -> ruch w lewo
jmp vert
right:; CF=1, ruch w prawo
cmp ah, 16 ; czy w ostatniej kolumnie?
je vert ; tak -> nie rusz
inc bx
;ruch pionowy:
vert: shr dl,1 ;
jc down
;cf=0, ruch w gore
cmp al, 0 ; pierwszy wiersz?
je done
sub bx, 17 ; wsp(w-1,k) = 17(w-1)+k = 17w+k-17 = wsp(w,k)-17
jmp done
down:;cf=1 ruch w dol
cmp al, 8 ; ostatni wiersz?
je done
add bx, 17 ; wsp(w+1,k) = wsp(w,k)+17
done:
mov al,dl ; zmien al ( shr al,2 )
pop cx
pop dx
popf
ret
MoveBishop endp
; HexToByte -------------------------------------------------
; Konwertuje hexy w AH:AL do pojedynczego bajtu w AL
; moze rzucic errorKeyVal'em
HexToByte proc
push dx
xor dh,dh ; dh=0, miejsce na wynik
call HexToNibble ; starszy na liczbe
add dh, ah
shl dh, 4 ; 1 hex to 4 bity
mov ah, al
call HexToNibble ; mlodszy na liczbe
add dh, ah
mov al, dh
pop dx
ret ; wyjscie z HexToByte
HexToByte endp
HexToNibble proc
cmp ah, '0'
; jb (below) - mniejszy bez znaku; CF=1
jb errorKeyVal ; (.. '0') - blad
cmp ah, '9'
jbe decimaldigit ; ['0' .. '9'] - ok
cmp ah, 'A'
jb errorKeyVal ; ('9' .. 'A') - blad
cmp ah, 'F'
jbe letter ; ['A' .. 'F'] - ok
jmp errorKeyVal ; ('F' ..) - blad
decimaldigit: ; znak od 0 do 9
sub ah, '0'
ret
letter: ; od A do F (wielkie litery)
sub ah, 55 ; A ma kod 65, reprezentuje 10
ret
HexToNibble endp
; ParseArgs -------------------------------------------------
; wczytaj argumenty z [80h] do struktury (argc,args,argv)
; wykorzystujac EatWS i CopyWord.
; przy wywolaniu rejestr DS powinien wskazywac na segment PSP
ParseArgs proc
pusha ; push AX, CX, DX, BX, SP, BP, SI, DI
xor cx,cx ; CX = 0
mov cl, byte ptr ds:[80h] ; cx na ilosc bajtow lini komend
mov si, 81h ; ds:[si] na poczatek bufora argumentow w PSP
mov ax, seg argv ;
mov es, ax ; es na segment danych
mov di, offset argv ; es:[di] na poczatek argv
iter:
call EatWS ; zmniejsz cx, zwieksz si
and cx,cx ; cmp cx,0
jz return ; Bufor byl pusty / zawieral same biale znaki
; dodaj nowy parametr do args
xor bh, bh ; Ustaw bx na
mov bl, byte ptr es:[argc] ; ilosc argumentow
shl bx, 1 ; bx *= 2, adresujemy word
mov word ptr es:[args+bx], di ; aktualne di jako adr tego parametru
inc byte ptr es:[argc] ; argc++
call CopyWord ; zmniejsz cx, zwieksz si+di
jmp iter
return:
popa ; odwrotnie do PUSHA, nie kopiuje SP, pomija go
ret
ParseArgs endp
; Eat WhiteSpace -------------------------
; przesun SI na pierwszy niebialy bajt
; zmienia: si, cx
EatWS proc
iter: ; wyjdz gdy bufor sie skonczyl
and cx,cx ; cx == 0 ?
jz return ; tak -> break
dec cx ; cx--
lodsb ; al = ds:[si] ; si++
; if ( bialy ) continue
jmpEq al, 20h, iter ; spacja
jmpEq al, 09h, iter ; \t tab
jmpEq al, 0Ah, iter ; \n line-feed
jmpEq al, 0Ch, iter ; \f form-feed
jmpEq al, 0Dh, iter ; \r carriage-return
; gdy niebialy:
inc cx ; "oddajemy" pobrany znak,
dec si ; cofajac sie w buforze
return:
ret
EatWS endp
; CopyWord --------------------------------------------------------
; kopiuj bajty z ds:[si] do es:[di], az do pierwszego bialego znaku
; przesun SI na pierwszy bialy, DI na miejsce na kolejny argument
; zmienia: si, di, cx
CopyWord proc
iter: ; wyjdz gdy bufor sie skonczyl
and cx,cx ; cx == 0 ?
jz return ; tak -> break
dec cx ; pobranie znaku:
lodsb ; al = ds:[si] ; si++
; if ( bialy ) break
jmpEq al, 20h, done ; spacja
jmpEq al, 09h, done ; \t tab
jmpEq al, 0Ah, done ; \n line-feed
jmpEq al, 0Ch, done ; \f form-feed
jmpEq al, 0Dh, done ; \r carriage-return
; gdy niebialy
stosb ; es:[di] = al, di++
jmp iter
done: ; petla trafila na bialy znak, koryguj indeksy
inc cx ; oddaj pobrany znak
dec si ; wroc w buforze
inc di ; zostaw 1 bajt (dolar) przerwy w argv
return:
ret
CopyWord endp
; Ponizsze procedury zakladaja, ze ds wskazuje na segment danych:
; GetArgNum --------------------
; zaladuj do AL ilosc argumentow
; (zaklada, ze ds wskazuje na segment danych)
GetArgNum proc
xor ax,ax ; AX = 0
mov al, byte ptr ds:[argc] ; kopiuj
ret
GetArgNum endp
; GetArgPos -----------------------------------
; zaladuj do AX adres argumentu o indeksie z DL
; (zaklada, ze ds wskazuje na segment danych)
GetArgPos proc
push bx
xor ax,ax ; AX = 0
mov al, dl ; AX = DL
shl ax, 1 ; AX*2, word ptr
mov bx, offset args
add bx, ax ; BX na args[DL]
; AX = adres DL-tego argumentu
mov ax, word ptr ds:[bx]
pop bx
ret
GetArgPos endp
; GetArgLen -------------------------------------
; zaladuj do AX dlugosc argumentu o indeksie z DL
; (zaklada, ze ds wskazuje na segment danych)
GetArgLen proc
push bx
call GetArgPos ; znajdz poczatek DL-tego argumentu
mov bx, ax
xor ax,ax ; ax = 0
lenLoop:
cmp byte ptr ds:[bx], '$'
je return
inc ax
inc bx
jmp lenLoop
return:
pop bx
ret
GetArgLen endp
_Kod ends
_Stos segment stack
; Rozmiar 80h w slowach (256d bajtow)
dw 7Fh dup(?)
wstosu dw ?
_Stos ends
end start
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment