Prosty program w Assemblerze pod Linuksa

Witam wszystkich :wink:

Mam takie zadanie i nie wiem czy go dobrze rozwiązałem. Proszę o pomoc bo nie mam w sumie się kogo podpytać wiec piszę tutaj :wink:

Zadanie brzmi:

Program ma wykonać działanie |(x-y)*z|, zmienne maja być przekazane przez rejestry kolejno %EBX, %ECX, %EDX, a wynik przekazany przez %EAX. Ma być zrealizowane za pomocą podprogramu. (czyli CALL i RET)

.text

.global _start



bez:


sub %ebx,%ecx

mul %ecx

cmp $0, %eax

jge end_if

neg %eax

end_if:

ret


_start:


mov $5, %ebx # y

mov $10, %ecx # x

mov $-10, %eax # z

xor %edx,%edx

call bez

nop

Przekazujesz przez EBX,ECX,EAX a w zadaniu napisano inaczej.

A liczysz to zupełnie coś innego - abs(eax*ecx)

!@#$% mój błąd. Zasugerowałem się podpowiedzą kolegi który za dużo nie wie podobnie do mnie i tym sposobem po minąłem sens polecenia :frowning:

Przerobiłem go i jak byś mógł powiedzieć czy jest okej ?

.text

.global _start



bez:


sub %ecx,%edx

mul %edx

cmp $0, %eax

jge end_if

neg %edx

end_if:

ret


_start:


mov $5, %ebx # x

mov $10, %ecx # y

mov $-10, %edx # z

xor %eax,%eax

call bez

nop

Matko jedyna.

X - ebx

Y - ecx

Z - edx

Tak? Chcesz (x-y), więc dlaczego odejmujesz:

sub %ecx,%edx

Masz ewidentnie błąd, bo operację przeprowadzasz na ecx (Y) i edx (Z). Przyłóż się trochę do tego kodu, zanim go wyślesz do oceny, ok?

…mam nadzieje, że Ciebie o zawał nie przyprawie…

Znalazłem nawet z tego wszystkiego kurs Asemblera http://komputery.katalogi.pl/%5Binfo%5D_Podstawy_asemblera_komputer%C3%B3w_PC-t47610.html

I znalazłem tam takie coś:

ADD parametr, parametr

SUB parametr, parametr

  • dodaj lub odejmij liczbę, tj. do pierwszego parametru wpisz sumę lub różnicę obydwu parametrów

Wiec widzę swój błąd i rozumiem dlaczego się załamałeś :wink:

Mam nadzieje, że dobrze poprawiłem:

.text

.global _start


bez:


sub %ebx,%ecx

mul %edx

cmp $0, %eax

jge end_if

neg %edx

end_if:

ret


_start:


mov $5, %ebx # x

mov $10, %ecx # y

mov $-10, %edx # z

xor %eax,%eax

call bez

nop

Obliczasz X-Y i zapisujesz “na ścianie”.

Zwracasz abs(0*Z)

Chyba nie o to chodziło?

Ok, spróbujemy tak. Jako że to GNU AS, składnia przewiduje źródło najpierw, cel później.

SUB P, Q

oznacza zatem

Q = Q - P

Jeśli chodzi o mnożenie, wynik jest zawsze większy (pod względem ilości bitów) niż źródło. Zatem:

  • wynik mnożenia AL * #L będzie w AX

  • wynik mnożenia AX * #X będzie w DX:AX

  • wynik mnożenia EAX * E#X będzie w EDX:EAX

Teraz wiesz jak to napisać?

Czyli mam rozumieć, że wynik mam najpierw zapisać ? A następnie dopiero mnożyć ?

Przepraszam za takie pytania… ale… mam takiego wykładowce co mówi, że… “na głupie pytania nie odpowiadam” i dlatego mam w głowie tyle niejasności :frowning:

Nim się zada mądre pytanie trzeba umieć, a żeby umieć muszą być jakieś początki :?

sub %ebx,%ecx

oznacza (o ile to GNU AS): zapisz do ecx wynik operacji ecx-ebx

Dalej do obliczeń ecx nie używasz.

Dobra. Odejmowanie rozumiem już doskonale jak i dodawanie.

sub %ebx,%ecx <-- odjąłem x (ebx) od y (ecx), wynik działania jest w ebx

mov %eax,%ebx <-- teraz wynik odejmowania (ebx) musiał bym przypisać do eax

mul %edx <-- przy mnożeniu teraz by było to tak, że liczbę z eax pomnożył bym przez edx i wynik był by w eax (dobrze wnioskuję???)

Też mi się wydaje, że mogło by być to następująco:

sub %ebx,%ecx <-- odjąłem x (ebx) od y (ecx), wynik działania jest w ebx

mul %edx,%ebx <-- teraz mnożę edx z ebx i wynik mnożenia zostaje w edx

mov %eax,%ebx <-- teraz wynik musi być w eax (tak zad pisze) wiec przypisuje wynik mnożenia do eax

Na chwilę obecną ja to tak rozumiem… mam nadzieje, że jest dobrze lub chociaż jest lepiej niż było :?

mul ma tylko jeden parametr, zawsze mnoży Al,AX,EAX przez to co podano

Czyli reasumując to kod ma wyglądać następująco:

sub %ebx,%ecx <-- Odejmuję ebx od ecx

mov %eax,%ebx <-- przypisuje do eax wartość ebx

mul %edx <-- mnoży wartość edx przez eax

Czyli całe zadanie ? Czy ja znów coś pomieszałem ? :?

Nie, wciąż nie rozumiesz. :wink: Widzisz różnicę? Ale ciężko Cię winić - GNU AS ma zwaloną kolejność argumentów. ;>

wynik odejmowania będzie w ecx.

nie, przypisujesz do ebx wartość eax.

zgadza się, tyle że w eax nadal jest zero.

Ale byka strzeliłem :-/

sub %ecx,%ebx

mov %ecx,%eax

mul %edx

Na odwrót powinno być :wink: Teraz jest już okej, prawdaaaa ? :?

Wciąż masz błąd w mov. Wynik odejmowania masz w ebx a nie ecx. Nie zgaduj, myśl. Prześledź działanie programu linia po linii. Ja rozumiem, że zgadywanie jest fajne, ale sekwencja sub-mov-mul na 4 rejestrach ma 1024 kombinacje i tylko jedna z nich jest w kontekście Twojego zadania poprawna. Zamiast na czuja próbować 1000 razy, napisz to raz a porządnie.

A tak przy okazji czy nie powinno być: subl , movl i td ?

GAS użyje rozmiaru wyniku, jeśli nie doda się sufixu.

U mnie na zajęciach nie używaliśmy movl, subl, itd wiec chyba nie powinno tak być.

Dzisiaj na świeżo popatrzałem na program i faktycznie jest błąd :? Teraz jest już dobrze :wink:

sub %ecx,%ebx

mov %ebx,%eax

mul %edx

Powiedzcie mi czy mov działa na tej samej zasadzie co sub lub add ?? Tzn chodzi mi o wynik, bo sub %ecx, %ebx zapisuje wynik do %ebx. Następnie mov %ebx, %eax zapisuje wartość do %eax ? Analogicznie myśląc to tak tylko, że już mnie nie raz zaskoczyliście wiec się pytam :?

sub zapisuje do ebx a mov do eax, bo drugim argumentem, który podałeś do sub jest ebx a w mov eax. Drugi argument przy dodawaniu i odejmowaniu to zarówno jeden z argumentów działania, jak i wynik.

add %eax, %ebx

oznacza: zsumuj eax i ebx i wynik zapisz w ebx. Bo ebx jest drugim argumentem. Gdybyś napisał

add %edx, %ecx

zsumowałbyć edx z ecx i wynik zapisał do ecx. Jeśli chodzi o mov, drugi argument jest celem, pierwszy źródłem

mov %eax, %ecx

oznacza, że chcesz przenieść z eax wartość do ecx (nadpisać ecx wartością z eax). Przy okazji dodam, że tak działają asemblery GNU. W niektórych kompilatorach, m.in. tych Microsoftu argumenty podaje się bez procentów i odwrotnie. Żeby było łatwiej. :wink: