Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Błąd w kodzie projektu

Bodziulla 06 Lut 2009 22:29 1413 3
  • #1 06 Lut 2009 22:29
    Bodziulla
    Poziom 9  

    Witam.
    Mam pytanie czy jest w stanie mi ktoś pomóc znaleźć błąd w kodzie i gdzie go popełniam. Może zacznę jest to program do szyfrowania i deszyfrowania w asm połączony z Delphi tzn szkielet programu zrobiłem w Delphi a sam kod miałem zrobić w asm (funkcja szyfrująca XOR).I tutaj pojawia się dla mnie problem, bo gdy zaczynam szyfrować i to pojawia się błąd "Scan line index out of range".Nie wiem jak mam to rozgryźdź a jest to dla mnie ważne na zaliczenie.
    Pozdrawiam

    a oto kod


    Code:
    unit Unit1;
    

    interface

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ExtCtrls, ExtDlgs, jpeg;

    type
      TForm1 = class(TForm)
        Image1: TImage;
        Label1: TLabel;
        Button1: TButton;
        Label3: TLabel;
        Edit1: TEdit;
        Button3: TButton;
        OpenPictureDialog1: TOpenPictureDialog;
        Label2: TLabel;
        SaveDialog1: TSaveDialog;
        Button4: TButton;
        procedure Button3Click(Sender: TObject);
        procedure Button4Click(Sender: TObject);
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;

    var
      Form1: TForm1;
    implementation

    {$R *.dfm}
    var

    img_path: string;
    img_key: string;
    img_loaded: integer;
    key: byte;

    procedure TForm1.Button3Click(Sender: TObject);
    begin
    if OpenPictureDialog1.Execute then begin
      img_path:=OpenPictureDialog1.FileName;
      Label2.Caption:=img_path; // wczytanie sciezki pliku do etykiety po otwarciu
      Label1.Visible:=true; // ustawienie widocznosci etykiety
      Image1.Picture.LoadFromFile(img_path); // zaladowanie zdjecia
      img_loaded:=1;
    end;
    end;

    procedure TForm1.Button4Click(Sender: TObject);
    begin
     if SaveDialog1.Execute then begin
      Image1.Picture.SaveToFile(SaveDialog1.FileName);
     end;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    var
    img_width,img_height,i,j,keylen: integer;
    is24bit: byte;
    img_ptr: PByteArray;
    begin
     is24bit:=0; // inicjalizacja
     key:=0; // inicjalizacja




     // Najpierw sprawdzenie, czy plik jest już załadowany
     img_key:=Edit1.Text;
     keylen:=length(img_key);
     if (keylen < 8 ) then begin
                   for i:=keylen to 8 do
                   img_key[i]:='0'; // Dopelnianie klucza 'zerami' ;p
     end;
     if (keylen > 8 )  then // skrocenie klucza
       img_key:=Copy(img_key, 1, 8 );
     
     asm
      push eax // zachowujemy na stos ( na wszelki wypadek )
      push ecx // uzywane rejestry
      push ebx
      push esi

      mov bh,128
      mov bl,2 
      mov ecx,8
      @@next_bit_generate:
      mov al, byte ptr img_key[esi] 
      xor ah,ah // zerujemy ah
      div bl
      cmp ah,1 // czy reszta == 1
      je @@set_one // ustawimy bit w zmiennej key
      jmp @@after_set // przeskok nad kodem ustawiajacym bit.
      @@set_one:
      or key,bh
      @@after_set:
      shr bh,1 
      inc esi
      loop @@next_bit_generate

      // przywrocenie rejestrow ze stosu
      pop esi
      pop ebx
      pop ecx
      pop eax
     end;
     ShowMessage('Klucz to '+inttostr(key));
     if(img_loaded=0) then begin // jesli nie zaladowano
      ShowMessage('Nie wczytano pliku obrazu.');
      exit;
     end;
     // Sprawdzenie ilosci bitow na piksel
     if Image1.Picture.Bitmap.PixelFormat=pf8bit then begin
      is24bit:=0;
      ShowMessage('8 bit');
     end;
     if Image1.Picture.Bitmap.PixelFormat=pf24bit then begin
      is24bit:=1;
      ShowMessage('24 bit');
     end;
     // Zmienne pomocnicze do petli
     img_height:=Image1.Height-1;
     img_width:=Image1.Width-1;

     ShowMessage('Wysokosc bitmapy: '+inttostr(img_height)+', szerokosc: '+inttostr(img_width)+'.');
     for i:=1 to img_height do begin
         img_ptr:=Image1.Picture.Bitmap.ScanLine[i];
         asm
          push eax
          push ecx
          push esi

          mov ecx,img_width
          xor esi,esi
          mov [key],ah 
          cmp is24bit,1
          je @@encode_next_cell24
          @@encode_next_cell8:
         
          xor byte ptr img_ptr[esi],ah
          inc esi 
          loop @@encode_next_cell8
          jmp @@after_loops
         
          @@encode_next_cell24: // wersja dla 24
          xor byte ptr img_ptr[esi],ah // xor na kolejnych skladowych piksela
          xor byte ptr img_ptr[esi+1],ah // R, G, B
          xor byte ptr img_ptr[esi+2],ah
          add esi,3  // zwiekszenie esi o 3
          @@after_loops:
         

          pop esi
          pop ecx
          pop eax
         end;
       end;
       Image1.Refresh;
       if Button1.Caption='Szyfruj' then Button1.Caption:='Deszyfruj'
       else
       Button1.Caption:='Szyfruj';
    end;

    procedure TForm1.Button2Click(Sender: TObject);
    begin
    // Sprawdzenie, czy w ogole cos wczytano
     if(img_loaded=0) then begin
      ShowMessage('Nie wczytano pliku obrazu.');
      exit;
     end;

    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
     img_loaded:=0;
    end;

    end.


    Kod proszę umieszczać w znacznikach code - krzychoocpp

    0 3
  • #2 07 Lut 2009 12:05
    Dżyszla
    Poziom 42  

    1. nie ma potrzeby zrzucania rejestrów na stos w momencie wejścia w blok asm - kompilator sam to implementuje.

    2. gdzie inicjacja wartości rejestru esi (pierwszy asm)?

    BTW - zamiast dzielić i sprawdzać resztę, radzę pszesuwać i sprawdzać CF.

    0
  • #3 07 Lut 2009 13:21
    Bodziulla
    Poziom 9  

    Hej witam.Dziękuję za szybkie zainteresowanie o postarałem się do Twoich wskazówek, ale chyba nie udolnie, bo nadal nie umiem tego rozpracować.Ale po pewnych zmianach program zaczyna oblicza faktycznie klucz jakiś na podstawie wpisanego ciągu, wiec jest lepiej.Ale przy przy szyfrowaniu zdjęcia bmp wykazuje, że jest 24 bit, ale gdy nacisnę, ok to wyskakuje komunikat "Access violation at address 0046DB1B in module "Projekt.exe".Read of address 000002FB". Nie wiem czy dobrze tłumaczę, bo nie jestem dobry z programowania w asm, ale za pomocą książek i notatek z wykładów postarałem się napisać owy program, ale jak się okazuje nie do końca potrafię

    pozdrawiam

    a to kod poprawiony

    Code:
    unit Unit1;
    

    interface

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ExtCtrls, ExtDlgs, jpeg;

    type
      TForm1 = class(TForm)
        Image1: TImage;
        Label1: TLabel;
        Button1: TButton;
        Label3: TLabel;
        Edit1: TEdit;
        Button3: TButton;
        OpenPictureDialog1: TOpenPictureDialog;
        Label2: TLabel;
        SaveDialog1: TSaveDialog;
        Button4: TButton;
        procedure Button3Click(Sender: TObject);
        procedure Button4Click(Sender: TObject);
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;

    var
      Form1: TForm1;
    implementation

    {$R *.dfm}
    var

    img_path: string; // Sciezka do pliku obrazu
    img_key: string; // tu przepiszemy stringa z kluczem
    img_loaded: integer; // tutaj zapisujemy pomocnicza informacje o tym, czy zaladowalismy juz obraz
    key: byte; // w tej zmiennej przechowywac bedziemy klucz do operacji XOR

    procedure TForm1.Button3Click(Sender: TObject);
    begin
    if OpenPictureDialog1.Execute then begin
      img_path:=OpenPictureDialog1.FileName;
      Label2.Caption:=img_path; // wczytanie sciezki pliku do etykiety po otwarciu
      Label1.Visible:=true; // ustawienie widocznosci etykiety
      Image1.Picture.LoadFromFile(img_path); // zaladowanie zdjecia
      img_loaded:=1;
    end;
    end;

    procedure TForm1.Button4Click(Sender: TObject);
    begin
     if SaveDialog1.Execute then begin
      Image1.Picture.SaveToFile(SaveDialog1.FileName);
     end;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    var
    img_width,img_height,i,j,keylen: integer; // kolejno zmienne dla dlugosci
    // obrazka, wysokosci, indeksy iteracyjne i dlugosc klucza podanego przez uzytkownika
    is24bit: byte; // ustawione na 0, jesli nie uzywamy skladowych RGB (24-bit bitmap)
    img_ptr: PByteArray; // wskaznik do obszaru bajtow
    begin
     is24bit:=0; // inicjalizacja
     key:=0; // inicjalizacja
     // Najpierw sprawdzenie, czy plik jest już załadowany
     img_key:=Edit1.Text;
     keylen:=length(img_key);
     if(keylen<8) then begin
                   for i:=keylen to 8 do
                   img_key[i]:='0'; // Dopelnianie klucza 'zerami' ;p
     end;
     if (keylen>8) then // skrocenie klucza
       img_key:=Copy(img_key,1,8);
       // Teraz kod majacy na celu ustawienie bitow klucza w zaleznosci
       // od podzielnosci przez 2 pierwszych 8 znakow "klucza"
     asm
      mov bh,128 // nasza maska do ustawiania bitow
      mov bl,2  // argument dzielenia uzyty do sprawdzania reszty
      mov ecx,8 // bo pracujemy na pierwszych 8 znakach.
      xor esi,esi // zerowanie esi
      @@next_bit_generate:
      mov al, byte ptr img_key[esi]  // wrzucenie obecnego znaku ze stringa do al
      shr al,1
      jc @@set_one // jesli wynik = 1, ( czyli  img_key[esi] mod 2 )
      jmp @@after_set // przeskok nad kodem ustawiajacym bit.
      @@set_one:
      or key,bh // ustawienie bitu ( kolejno od najstarszego z kazda iteracja )
      // w zmiennej klucza na podstawie maski, jaka jest w bh (128,64,32,16,8,4,2,1)
      @@after_set:
      shr bh,1  // przesuniecie w prawo maski ( czyli podzielenie przez 2 )
      inc esi
      loop @@next_bit_generate

     end;
     ShowMessage('Klucz to '+inttostr(key));
     if(img_loaded=0) then begin // jesli nie zaladowano
      ShowMessage('Nie wczytano pliku obrazu.');
      exit;
     end;
     // Sprawdzenie ilosci bitow na piksel
     if Image1.Picture.Bitmap.PixelFormat=pf8bit then begin
      is24bit:=0;
      ShowMessage('8 bit');
     end;
     if Image1.Picture.Bitmap.PixelFormat=pf24bit then begin
      is24bit:=1;
      ShowMessage('24 bit');
     end;
     // Zmienne pomocnicze do petli
     img_height:=Image1.Height-1;
     img_width:=Image1.Width-1;
     // Tutaj główna częsc zadania, procedura szyfrujaca XOR
     // Notatka procedury kodowania w pascalu
     // Dla bitmap 24 bitowych robimy tak:
     //  img_ptr[3*j]:=img_ptr[3*j] xor key;
     //  img_ptr[3*j+1]:=img_ptr[3*j+1] xor key;
     //  img_ptr[3*j+2]:=img_ptr[3*j+2] xor key;
     //  zas dla 8bitowych po prostu xor img_ptr[j]
     ShowMessage('Wysokosc bitmapy: '+inttostr(img_height)+', szerokosc: '+inttostr(img_width)+'.');
     for i:=1 to img_height do begin
         img_ptr:=Image1.Picture.Bitmap.ScanLine[i];
         asm
          mov ecx,img_width // ustawienie licznika iteracji na ilosc linii w obrazie
          xor esi,esi // szybkie zerowanie esi, bedziemy nim indeksowac piksele
          mov [key],ah  // wpisanie 8-bitowego klucza do rejestru ah
          cmp is24bit,1 // sprawdzenie, czy  bitmapa ma 24 bity ( czy is24bit==1 )
          je @@encode_next_cell24 // przeskosk do wersji dla 24
          @@encode_next_cell8: // wersja dla 8
          // Tutaj nastepuje xor wartosci piksela danych obrazu z 8-bitowym kluczem.
          xor byte ptr img_ptr[esi],ah // wykonanie operacji xor na wartosci piksela z kluczem znajdujacym sie w ah
          inc esi  // zwiekszenie esi, czyli indeksu kolejnego bitu.
          loop @@encode_next_cell8 // petla dla 8-bitowej mapy
          jmp @@after_loops // przeskok na koniec, jesli mapa miala 8 bitow
          // oddzielny kod dla 24 bitowych map ( aby zaoszczedzic operacji w ciagu kodowania kazdego bajta )
          // tj. aby nie robic sprawdzenia, jaki jest typ mapy z kazda iteracja
          @@encode_next_cell24: // wersja dla 24
          xor byte ptr img_ptr[esi],ah // xor na kolejnych skladowych piksela
          xor byte ptr img_ptr[esi+1],ah // R, G, B
          xor byte ptr img_ptr[esi+2],ah
          add esi,3  // zwiekszenie esi o 3
          @@after_loops: // etykieta zaraz po zakonczeniu petli, sluzy do ewentualnego przeskakiwania
          // wersji kodowania dla 24 bitow (jmp @@afterloops)
         end;
       end;
       Image1.Refresh;
       if Button1.Caption='Szyfruj' then Button1.Caption:='Deszyfruj'
       else
       Button1.Caption:='Szyfruj';
    end;

    procedure TForm1.Button2Click(Sender: TObject);
    begin
    // Sprawdzenie, czy w ogole cos wczytano
     if(img_loaded=0) then begin
      ShowMessage('Nie wczytano pliku obrazu.');
      exit;
     end;

    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
     img_loaded:=0;
    end;

    end.


    Dodano po 3 [minuty]:

    No i jeszcze małe sprostowanie, bo przy wysłaniu kodu nie dopatrzyłem błędu, że zamiast obrazków to jest liczba 8.Przepraszam za głupi błąd

    Kod proszę umieszczać w znacznikach code! To już drugie upomnienie - krzychoocpp

    0