Pop i push w asm.

Odpowiedz Nowy wątek
2011-03-06 09:57
0

Mam jedno pytanie odnośnie instrukcji pop i push w asemblerze, mianowicie, który kod jest poprawniejszy. Oczywiście oba programy będą działały tak samo, chodzi mi bardziej o konwencję i dobre nawyki w korzystaniu z pop i push.

1:

LABEL1:
 pop r17
 pop r16
 (KOD A)
 (KOD B)
 push r16
 push r17
 rjmp MAIN

LABEL2:
 pop r17
 pop r16
 (KOD C)
 (KOD B)
 push r16
 push r17
 rjmp MAIN

2:

LABEL1:
 pop r17
 pop r16
 (KOD A)
 rjmp LABEL3

LABEL2:
 pop r17
 pop r16
 (KOD C)
 rjmp LABEL3

LABEL3:
 (KOD B)
 push r16
 push r17
 rjmp MAIN

EDIT: Poprawiłem błędy w kolejności instrukcji.

edytowany 3x, ostatnio: gamer, 2011-03-07 09:21

Pozostało 580 znaków

2011-03-06 13:15
msm

W ogólności - kod 1. Lepszy z punktu widzenia czytelności (dla człowieka) i szybszy (unikamy niepotrzebnych skoków). Chyba że label1-label3 są ściśle związane - w jednej funkcji - wtedy można potraktować pop jako prolog funkncji.

Pozostało 580 znaków

2011-03-06 19:13
0

Mhm rozumiem, dzięki wielkie za szybką odpowiedź. :)

Pozostało 580 znaków

2011-03-06 19:48
0
  1. Mieszasz w kolejności wpychania/ pobierania rejestrów na stos. Stos to kolejka LIFO, tzn jeśli chcesz zachować wartości dwóch rejestrów i je potem wczytać to robisz: push r1, push r2, <tu kod="kod">, pop r2, pop r1
  2. Co do pytania to zależy od długości kodu B. Jeśli jest długi to po co go powtarzać?
  3. Nie bój się robić funkcji i wywoływać ich instrukcją call. W miarę nowe procesory x86 posiadają stos calli, tzn call wpycha wtedy aktualny adres nie tylko na stos ogólny, ale także na stos calli wewnątrz procesora. Ten wewnętrzny stos jest swego rodzaju podpowiedzią na temat tego, gdzie może prowadzić następna instrukcja ret (powrotu z procedury) - dzięki temu procesor może wykonać odpowiedni prefetching kodu.

"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
Ad. 1 Oczywiście, coś mi się rypło przy wpisywaniu. - gamer 2011-03-07 09:07

Pozostało 580 znaków

2011-03-06 20:03
msm
0

1 -> myślę że tutaj jednak chodzi o pobranie parametrów ze stosu z wywołania funkcji. W przypadku pisania większych funkcji warto byłoby poczytać o ramce stosu - technika umożliwiające/upraszczająca definiowanie parametrów i zmiennych lokalnych (np. http://osdev.labedz.org/imple[...]/laczenie_procedur/ramka.html, http://pl.wikibooks.org/wiki/Asembler_X86/Funkcje/NASM). Jeśli dobrze zgaduje, wtedy push r1 push r2 można zamienić po prostu na modyfikację rejestru esp.

2 -> Jeśli jest długi (dłuższy niż sam push zmiennych) to znaczy prawdopodobnie że jest to część jednej funkcji. Ciężko mi sobie wyobrazić dużo powtarzającego się kodu w dwóch zupełnie różnych funkcjach - jeśli jednak tak jest to... ja bym wydzielił z tego kolejną funkcję - czyli:

LABEL1:
 pop r17
 pop r16
 (KOD A)
 call FUNCTION_B
 push r16
 push r17
 rjmp MAIN

LABEL2:
 pop r17
 pop r16
 (KOD C)
 call FUNCTION_B
 push r17
 push r16
 rjmp MAIN

3 -> skąd wiesz że autor nie używa?

Pozostało 580 znaków

2011-03-06 20:14
0

MASM czy standardowe makra FASMa (ew inne asembler) automatycznie dodają epilogi i prologi procedur i dodają mapowania parametrów na odpowiednie adresy względem aktualnej ramki stosu. Gdyby kolega chciał tutaj używać procedur to chyba by nie pisał takiego kodu.

Trzeba sobie zapamiętać bardzo ważne zasady:

  1. Ładowanie kodu z RAMu czy chociażby pamięci podręcznej dalekiego poziomu zajmuje dużo więcej czasu niż wykonanie tego kodu (jednokrotne). Morał z tego taki, że kod rzadko wykorzystywany, albo wykorzystywany w dość dużych odstępach czasu (np kilkadziesiąt milisekund) pasuje optymalizować pod względem rozmiaru, a kod wykonywany w pętlach (ale takich, że mieszczą się w szybkiej pamięci podręcznej kodu) należy optymalizować pod względem wykorzystania potoków wykonawczych.
  2. Podstawowa zasada optymalizacji to: nie optymalizuj. Druga zasada optymalizacji brzmi: jeszcze nie optymalizuj. Zalecam najpierw pisanie czytelnego kodu, a dopiero potem sforkowanie tego i stworzenie nieczytelnego i szybkiego potwora.

"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 2x, ostatnio: Wibowit, 2011-03-06 20:18

Pozostało 580 znaków

2011-03-07 09:18
0

Stawiam pierwsze kroki w programowaniu niskopoziomowym i staram się wyszukiwać najlepsze rozwiązania, nie tylko działające, ale też możliwie poprawne i sensowne. Konwencje są równie ważne jak sama składnia języka, mam dwie książki, na których bazuję, ale czasem kilka słów ludzi z doświadczeniem lepiej rozwiązuje kłopotliwe kwestie. :D

Dziękuję za pomoc.

edytowany 1x, ostatnio: gamer, 2011-03-07 09:19

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