Assembler w Delphi

Odpowiedz Nowy wątek
2006-08-29 23:32
0

Witam. Zacznę od tego ze w assemblerze piszę od kilku godzin.
Potrzebowałem funkcji do zapisywania i odczytywania bitów.

Oto owoc mojej pracy:

program Project1;
{$APPTYPE CONSOLE}
 
function GetBit(Val, Index: Byte): Byte;
asm
      MOV  CL, DL
      SHR  AL, CL
      AND  AL, 01h
end;
 
procedure PutBit(Val: PByte; Index, Bit: Byte);
asm
      AND EDX, 0ffh
      CMP CL, 00h
      JE  @lb1
      BTS [EAX], DX
      JMP @end
@lb1: BTR [EAX], DX
@end: // end
end;
 
var
  B: Byte;
  I: Integer;
begin
  B := 138; // 10001010b
  PutBit(@B, 5, 1); // 10101010b
  for I := 7 downto 0 do Write(GetBit(B, I));
  ReadLn;
end.

Wygląda, że działa. Mam tylko kilka pytań:

  1. Zauważyłem że argumenty trafiają do rejestrów tyle że jakoś dziwnie (A, D i C) czy zawsze tak jest?
  2. Jak argument Index typu Byte jest w DL to w całym EDX jest jakaś inna liczba. Dlaczego?
  3. Czy zawsze wynik funkcji trzeba wstawić do EAX, AX lub AL ?
  4. W funkcji GetBit tam gdzie jest SHR AL, CL; próbowałem wstawić DL zamiast CL, ale program się nie chciał skompilować. Czemu tylko CL ?
  5. Czy te funkcje można napisać lepiej. Jeżeli tak to jak?
  6. Jak napisać funkcję, która zwróci 4 argument? Chodzi mi o ten tajemniczy stos? Czytałem gdzieś, że tam trafiają argumenty, które nie trafią do rejestrów. Próbowałem coś kombinować, ale nic mi z tego nie wychodziło.

Pozostało 580 znaków

2006-08-30 09:41
0
  1. Domyslnie, polecam fraze calling conventions w hlp lub google.
  2. Bo nie ma sensu zerowac rejestru (jest tam jakas przypadkowa liczba a cie nie i tak interesuje tylko 8 bitow z EDX.
  3. Patrz 1 :)
  4. Ogolnie ECX jest wykorzystywany do roznego rodzaju loopow, to taka jego wlasciwosc :)
  5. Result := (Value shr Index) and 1; // :P, naprawde nie ma sensu zaprzegac do takich rzeczy asma.
  6. No coz, do opeacji na stosie sluza instrukcje POP i PUSH lub kazde inne operujace na pamieci dzieki ESP (w ktorym jest polozenie wierzcholka stosu). Co kompilator to inaczej odklada parametry wiec tu raczej nic nie moge podpowiedziec.

Pozostało 580 znaków

2006-08-30 09:59
0
  1. Nie ten dział - to powinno być w Delphi/Pascal...
  2. Poczytaj o konwencjach wywołania.
  3. Zgadzam się z Wolverinem :)
  4. Czasami nie - zobacz Asm
  5. Tylko dla instrukcji SHL z drugim parametrem stałym lub rejestrem licznika (ECX, CX, CL) istnieją opkody (odpowiedniki w kodzie maszynowym). Dla innych instrukcji obsługiwana jest tylko jedna rodzina rejestrów w danym miejscu (np. OUT przyjmuje dla pierwszego słowo maszynowe lub DX, dla drugiego EAX, AX, AL lub stałą wartość)
  6. Na pewno można napisać czytelniej ;P Odwołuj się do parametrów przy pomocy nazw. I nie tylko do tych odkładanych na stos.
  7. Patrz 5.

php if ($crazy) sqrt() or die;

Pozostało 580 znaków

2006-09-01 00:09
0

Dziękuję serdecznie za odpowiedzi.
Poczytałem trochę.
Argumenty funkcji znalazłem, ale dopiero pod ESP+8 niezależnie od konwencji wywołania. (różnica jest tylko w kolejności)
No i tu jest właśnie pytanie, czemu 8 bajtów dalej? Co jest wcześniej, nie potrafiłem tego zidentyfikować.

BTW udało mi się napisać funkcję PutBit lepiej: (te BTS i BTR są jakieś wolne)

procedure PutBitA(Val: PByte; Index, Bit: Byte);
asm
      PUSH CX;
      MOV  CL, DL;
      MOV  DL, 01h
      SHL  DL, CL
      POP  CX;
      CMP  CL, 00h
      JE   @lb1
      OR   [EAX], DL
      JMP  @end
@lb1: NOT  DL
      AND  [EAX], DL
@end: // end
end;

ale potem napisałem ją w Delphi i okazała się być szybsza o kilkanaście milisekund przy dużych danych:

procedure PutBitD(Val: PByte; Index, Bit: Byte);
var
  B: Byte;
begin
  B := 1 shl Index;
  if Bit = 0 then
    Val^ := Val^ and (not B)
  else
    Val^ := Val^ or B;
end;

dziwne bo jak ją oglądałem w debugerze to wyglądała podobnie tylko jest TEST zamiast CMP i jakiś rejestr ESI użyty.

Jeszcze raz dzięki za pomoc.


Pozostało 580 znaków

2006-09-01 07:48
0

Te 8 bajty odklada instrukcja CALL, ktora zostawia na stosie stary IP i CS zeby pozniej mozna bylo powrocic z funkcji.


Pozostało 580 znaków

2006-09-01 14:12
0
Wolverine napisał(a)

Te 8 bajty odklada instrukcja CALL, ktora zostawia na stosie stary IP i CS zeby pozniej mozna bylo powrocic z funkcji.

sorry, ale się nie zgodzę - tylko EIP, w końcu do delphi więc cs nie jest potrzebny /może w pascalu jest cs i ip ale i to i to ma po 2 bajty/... mnie to wygląda trochę jak zmienne lokalne funkcji wywołującej ew. zachowane rejestry... bez wrzucenia w\w kodu pod debugger lub disassember nie da się stwierdzić co tam jest faktycznie :/ Gdyby to była metoda klasy to pod esp+4 byłby this.


I nie udawaj, że rozumiesz.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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