Opublikowano: 25-04-2017



Dodawanie, odejmowanie, przenoszenie wartości to ważne elementy każdego języka - zobaczmy, jak wygląda to w assembly.

Po tytule i wstępie można sądzić, że pokażę, jak wyglądają instrukcje podstawowych operacji... ale nie ma to sensu. Ich lista jest dostępna w x64 Cheat Sheet (s. 2), a przykłady można wygenerować samodzielnie. Spójrzmy jednak na dodawanie liczb:

Oprócz znanego już prologu i epilogu funkcji widzimy dwie nowe linie. Pierwsza z nich przypisuje wartość 0 do miejsca w pamięci o adresie -4(%rbp). Druga natomiast odpowiada za dodanie 1 (pierwszy argument) do wartości znajdującej się pod adresem -4(%rbp) - od rejestru rbp odejmowane są 4 bajty, gdyż właśnie taki rozmiar ma, w naszym przypadku, typ int.

Wyraźnie widać tu zasadę działania instrukcji - weź wartość pierwszego argumentu, weź wartość drugiego argumentu, wykonaj określoną operację, a następnie wynik umieść w drugim argumencie. Operacje mogą być wykonywane [1, s.169]:

  • z miejsca w pamięci do rejestru:

    movl (%rbp), %eax
    
  • z rejestru do miejsca w pamięci:

    movl %eax, (%rbp)
    
  • pomiędzy rejestrami:

    movl %ebx, %eax
    
  • na konkretnych danych i pamięci, czy rejestrze:

    movl $5, (%rbp)
    movl $5, %eax
    

Uwagę przykuwają nazwy tych instrukcji, szczególnie dodatkowa litera l. Symbolizuje ona rozmiar danych, na których będziemy operować. Litera b oznacza 1 bajt (byte), w 2 bajty (word), l 4 bajty (long) oraz q 8 bajtów (quadword). Łatwo zatem rozpoznać, że movl operuje na 4 bajtach, a movq na 8 bajtach.

Jak widzimy każdy element musi być ze sobą zgodny pod względem rozmiaru danych, na których operuje - ilość zarezerwowanej pamięci na stosie, nazwa instrukcji, nazwa rejestru. O stosie oraz rejstrach możesz przeczytać w poprzednich wpisach.

Na dzisiaj to już koniec, ale do zobaczenia w przyszłym tygodniu!



Comments powered by Disqus