[ASM] Odczyt z pliku, kody ASCII

0

Witam.

Mam mały problem.

Otóż ogólna idea wygląda tak. Odczytuje zawartość pliku do bufora. Następnie chciałbym z bufora pobierać każdy znak po kolei (jeden za drugim) ale w postaci kodu ASCII - następnie kod jest przekazywany do modułu odpowiedzialnego za szyfrowanie RSA (to jest już zrobione).

Odczyt z pliku wygląda tak :

ReadFromFile PROC

	LOCAL hLog  :DWORD      ; file handle
    LOCAL fsiz  :DWORD      ; file size
    LOCAL bwrt  :DWORD      ; bytes written
    
    mov bwrt, 0
    
    invoke CreateFile,ADDR logfile,GENERIC_READ,
           FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL
    mov hLog, eax

    invoke GetFileSize,hLog,NULL            ; get the file size
    mov fsiz, eax

    invoke ReadFile,hLog,ADDR buffer,fsiz,ADDR bwrt,NULL

    invoke MessageBox,0,ADDR buffer,ADDR msgbox_title,0

    invoke CloseHandle,hLog                 ; close the file handle

    ret
ReadFromFile ENDP

I teraz moje pytanie brzmi. W jaki sposób pobierać kody ASCII poszczególnych znaków ?

Próbowalem tak :

mov esi, 0
	mov eax, 0

	.WHILE buffer[esi] != 0
		mov eax, dword ptr buffer[esi]

                ;TUTAJ CHCE WYWOŁYWAĆ PROCEDURĘ PRZYJMUJĄCĄ JAKO PARAMETR KOD ASCII ZNAKU 
                ; Z BUFORA

		inc esi
	.ENDW

ale to raczej nie jest poprawne rozwiązanie :)

Z góry dziękuję za pomoc.

Pozdrawiam

0
Herk napisał(a)
mov eax, dword ptr buffer[esi]

Kody ASCII są "8" bitowe, a nie 32 bitowe.

mov esi, buffer

; w jakiejś pętli

mov al, byte ptr [esi+ecx] ; <--- ecx to index
...
0

Faktycznie :)

Dziękuję.

Jeszcze jedno pytanko.

Aby zawartość al (czyli kod ascii) była traktowana jako liczba to muszę zamienić kod na liczbę ?

Pozdrawiam.

0

No przecież kod ASCII to liczba, więc co tam chcesz zamieniać? :|

0

Możesz zerknąć na ten kod ?

Procedura odpowiedzialna za kodowanie danych :

;a - to jest wlaśnie kod ascii
; w oraz n klucze generowane za pomocą innej funkcji
POT_MOD PROC a:DWORD, w:DWORD, n:DWORD

	LOCAL pot:DWORD, wyn:DWORD ,q:DWORD
	LOCAL reszta:DWORD
	LOCAL temp_1:DWORD, temp_2:DWORD
	
	;pot = a
	mov eax, a
	mov pot, eax
	
    ;wyn = 1
    mov wyn, 1
    
    ;q = w
    mov eax, w
    mov q, eax
    
    ;while(q > 0)
 
    .WHILE q > 0
    
		;if((q % 2) != 0)
		;reszta = q % 1
		mov eax, 0	; zerowanie rejestrow
		mov ecx, 0  ; zerowanie rejestrow
		mov edx, 0  ; zerowanie rejestrow
			
		mov eax, q
		mov ecx, 2
		div ecx
		mov reszta, edx
		
		.IF reszta != 0
			; wyn = (wyn * pot) % n;
			
			;wyn * pot
			mov eax, wyn
			mul pot
			mov temp_1, eax
			
			mov eax, 0
			mov ecx, 0
			mov edx, 0
			
			mov eax, temp_1
			mov ecx, n
			div ecx
			mov wyn, edx
		.ENDIF
		
		;pot = (pot * pot) % n;
		
		mov eax, pot
		mul pot
		mov temp_2, eax
		
		mov eax, 0
		mov ecx, 0
		mov edx, 0
		
		mov eax, temp_2
		mov ecx, n
		div ecx
		mov pot, edx
		
		;q = q / 2
		mov eax, 0
		mov ecx, 0
		mov edx, 0
    	
		mov eax, q
		mov ecx, 2
		div ecx
		mov q, eax	
		
    .ENDW
  
	mov eax, wyn
    mov EncodeMessage, eax
	
	ret
POT_MOD ENDP

Definicja procedury pobierającej znak z bufora i wywołanie procedury szyfrującej :

TEST_ASCII PROC

	LOCAL temp:byte

	mov esi, 0
	mov eax, 0
	mov ecx, 0
	
	mov esi, offset STRING
	
	.WHILE STRING[ecx] != 0
		mov al, byte ptr [esi+ecx]
		mov temp, al
		invoke POT_MOD, temp, 2324, 243276
		inc ecx
	.ENDW


	invoke MessageBox,0,ADDR STRING,ADDR msgbox_title,MB_OK
	
	ret
TEST_ASCII ENDP

Nie wiem dlaczego, ale dla zmiennej temp zawierającej kod ASCII danego znaku wynik procedury szyfrującej jest zawsze równy 0, a nie powinien. Gdy na sztywno podaje jakieś liczby wszystko działa jak trzeba - na sztywno tzn. z poziomu C++ jako argumenty funkcji.

0

najpewniej chodzi o błąd adresu zmiennej temp-zamiast niego pobiera z jakiegoś przypadkowego miejsca z pamięci i stąd wynikiem są zera.
Sprawdź pod debuggerem,czy dane do szyfrowania NA PEWNO pobiera spod właściwego adresu-dla testu najlepiej wprowadź go ręcznie w odpowiedni rejestr

poza tym widzę jeszcze taki błąd w deklaracji procedury:

POT_MOD PROC a:DWORD, w:DWORD, n:DWORD

winno być

POT_MOD PROC a:BYTE, w:DWORD, n:DWORD

skoro wysyłasz tutaj tylko 1 bajt.Jeśli wysyłałeś 4,i chciałeś odczytać potem jako bajt,to pobierał najstarszy bajt z 4,zawsze równy zero ;]
Ponadto WSZĘDZIE w ciele procedury POT_MOD musisz pozmieniać odwołania do zmiennej lokalnej a z 32 bitów na 8,ot na przykład początek:
mov eax,a
mov pot,a
na
mov al,a
mov pot,al (tutaj i definicję zmiennej pot z dword na byte też pamiętaj zmienić)

itd...

imho takie są powody nieprawidłowego działania tego kodu

0

No to sprawa się komplikuje w momencie gdy robię dzielenie modulo.

Dziele dwie liczby 32 bitowe a wynik muszę zapisać do zmiennej pot która jest 8 bitowa.

Makabra :)

Myślałem jeszcze nad takim rozwiązaniem (co ułatwiłoby mi późniejsze działania).

Otóż, pobierać 4 znaki ASCII, zamieniać je na liczby binarne i robić paczki po 8 bitów co dawałoby paczkę 32 bitową - muszę zachować jakiś schemat, żeby potem było wiadomo jak te dane odszyfrować - po 32 bity.

Możecie mi napisać czy będzie to dobre rozwiązanie ? Takie łączenie bitów.

Pozdrawiam.

0

Możesz też tak zrobić:

LOCAL temp:DWORD
	
;...
	
movsx eax, byte ptr [esi+ecx] ;<--- lub movzx
mov temp, eax
	
;...

wtedy w POT_MOD nie będziesz musiał nic zmieniać.

0

skoro wynikiem ma być zaszyfrowany kod ASCII,to z tego dzielenia 32/32 powinieneś uzyskiwać liczbę z przedziału 0-255.Skoro tak,to nie ma problemu bo wynik i tak znajdzie się w rejestrze AL ;]:
div ebx (w eax i ebx 2 liczby 32bit)
mov zaszyfrowana,al (przy założeniu iż wynikiem ma być ASCII,to po podzieleniu wynik zmieści się w AL)

a co do łączenia danych w paczki-zapoznaj się z instrukcjami MMX ;)

co do rozszerzania danych 8bit na 32bit to brat 0x666 podał ci dobry sposób :)

0

Dziękuję za pomoc i wskazówki.

0

Jeszcze jedno małe pytanko :) w sprawie "pakowania" danych.

Otóż, czy można zrobić tak :

Mam zmienną

ascii DD ?   ; czyli zmienna 32-bitowa

Następnie mam jakieś 4 liczby binarne (8 bitowe) i chce je przenieść do tej zmiennej.
Robię to w ten sposób, ale raczej błędny :)

 
        mov esi, offset ascii

        mov [esi], 00000001b
	mov [esi+8], 00000011b
	mov [esi+16], 00000111b
	mov [esi+24], 00001111b

Czy w ogóle taki tok rozumowania jest dobry ?

Pozdrawiam.

0
    mov esi, offset ascii

        mov [esi+0], 00000001b
        mov [esi+1], 00000011b
        mov [esi+2], 00000111b
        mov [esi+3], 00001111b

1 w dec = 8 bitow.

+3 = +24 bity.

I zastanow sie nad uzyciem zmienna RD 1 na koncu sekcji jesli piszesz pod coff.

0

Nie chce zaśmiecać forum, więc zapytam w tym wątku.

Nowy problem :-)

Problem pojawił się w momencie deszyfrowania wiadomości. Szyfrowanie działa jak należy.

Wszystko działa tak. Odczytuje dane z pliku i zapisuje je w buforze.

Następnie pobieram kolejno kody ASCII z bufora i przekazuje je do procedury szyfrującej :

POT_MOD PROC a:DWORD, w:DWORD, n:DWORD

	LOCAL pot:DWORD, wyn:DWORD ,q:DWORD
	LOCAL reszta:DWORD
	LOCAL temp_1:DWORD, temp_2:DWORD
	
	mov pot		, 0
	mov wyn		, 0
	mov q		, 0	
	mov reszta	, 0
	mov temp_1	, 0
	mov temp_2	, 0
	
	;pot = a
	mov eax, a
	mov pot, eax
	
    ;wyn = 1
    mov wyn, 1
    
    ;q = w
    mov eax, w
    mov q, eax
    
    ;while(q > 0)
 
    .WHILE q > 0
    
		;if((q % 2) != 0)
		;reszta = q % 1
		mov eax, 0	; zerowanie rejestrow
		mov ecx, 0  ; zerowanie rejestrow
		mov edx, 0  ; zerowanie rejestrow
			
		mov eax, q
		mov ecx, 2
		div ecx
		mov reszta, edx
		
		.IF reszta != 0
			; wyn = (wyn * pot) % n;
			
			;wyn * pot
			mov eax, wyn
			mul pot
			mov temp_1, eax
			
			mov eax, 0
			mov ecx, 0
			mov edx, 0
			
			mov eax, temp_1
			mov ecx, n
			div ecx
			mov wyn, edx
		.ENDIF
		
		;pot = (pot * pot) % n;
		
		mov eax, pot
		mul pot
		mov temp_2, eax
		
		mov eax, 0
		mov ecx, 0
		mov edx, 0
		
		mov eax, temp_2
		mov ecx, n
		div ecx
		mov pot, edx
		
		;q = q / 2
		mov eax, 0
		mov ecx, 0
		mov edx, 0
    	
		mov eax, q
		mov ecx, 2
		div ecx
		mov q, eax	
		
    .ENDW
  
	mov eax, wyn
    mov EncodeMessage, eax
	
	ret
POT_MOD ENDP

Wszystko ładnie. Daje poprawną wartość, ale...

Procedura generuje poprawne wyniki tylko dla liczb (kodów ASCII) w zakresie od 0 do 190 - a kody ASCII mają zakres 0 - 255. Szyfrowanie / deszyfrowanie wygląda tak :

	;testowe kodowanie danych
	LOCAL message:DWORD
	
	LOCAL encoding:DWORD
	LOCAL decoding:DWORD
	
	mov message, 190
	
	mov EncodeMessage, 0
	
	; kodowanie
	invoke POT_MOD, message, 3, 187
	mov eax, EncodeMessage
	mov encoding, eax
	xor eax, eax
	
	mov EncodeMessage, 0
	

;TUTAJ DLA LICZB WIĘKSZYCH NIŻ 190 POJAWIAJĄ SIĘ PROBLEMY TJ. WIADOMOŚĆ JEST
;NIEPOPRAWNIE DESZYFROWANA
	;dekodowanie
	invoke POT_MOD, encoding, 107, 187
	mov eax, EncodeMessage
	mov decoding, eax

Chodzi chyba o to, że dla liczb powyżej 190 wartości są zbyt duże i coś gubi się w rejestrach.
Jeśli dobrze myślę, to jak to obejść ?

A może problemem jest coś innego.

Na tej stronie w tabelce Rozszyfrowywanie kluczem prywatnym RSA :

http://www.i-lo.tarnow.pl/edu/inf/alg/primes/pages/020.php

Jest opisane (chyba) jak sobie z tym poradzić, ale za bardzo nie potrafię tego zaimplementować w asemblerze.

Myślałem jeszcze nad takim rozwiązaniem :

Pobieram znak ASCII.
Sprawdzam czy jest mniejszy od 180.
Jeśli nie, odejmuje od niego różnicę (kod ASCII - 75).
Taką wartość zapisuje w rejestrze i zmieniam znak ( najstarszy bit na 1) - żeby przy deszyfrowaniu wiedzieć, że do odszyfrowanego kodu muszę dodać 75.
Przy deszyfrowaniu pobieram liczbę, sprawdzam znak, jeśli najstarszy bit = 1 to zmieniam znak, deszyfruje, do kodu ASCII dodaje 75.

Co o tym myślicie ?

Z góry dziękuję za pomoc.

Pozdrawiam.

0

.WHILE q > 0

	;if((q % 2) != 0)
	;reszta = q % 1
	mov eax, 0	; zerowanie rejestrow
	mov ecx, 0  ; zerowanie rejestrow
	mov edx, 0  ; zerowanie rejestrow
		
	mov eax, q
	mov ecx, 2
	div ecx
	mov reszta, edx
	
	.IF reszta != 0
		; wyn = (wyn * pot) % n;
		
		;wyn * pot
		mov eax, wyn
		<b><span style="color: red">mul pot</span></b>
		mov temp_1, eax
		
		mov eax, 0
		mov ecx, 0
		mov edx, 0
		
		mov eax, temp_1
		mov ecx, n
		div ecx
		mov wyn, edx
	.ENDIF
	
	;pot = (pot * pot) % n;
	
	mov eax, pot
	<span style="color: red"><b>mul pot</b></span>
	mov temp_2, eax
	
	mov eax, 0
	mov ecx, 0
	mov edx, 0
	
	mov eax, temp_2
	mov ecx, n
	div ecx
	mov pot, edx
	
	;q = q / 2
	mov eax, 0
	mov ecx, 0
	mov edx, 0
	
	mov eax, q
	mov ecx, 2
	div ecx
	mov q, eax	
	
.ENDW

sprawdź w zaznaczonych miejscach debbugerem,czy przy tych działaniach edx na pewno jest równy zero.
Ponadto wciąż widze u ciebie Bracie działanie na liczbach 32 bitowych,gdy tymczasem pracujesz na ASCII.Upewnij się,iż istotnie pobierasz z bufora JEDEN bajt za każdym razem

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