2010-12-27 11 views
5

Podczas czytania przez jakiegoś kodu źródłowego w projekcie GNU, natknąłem się na ten kawałek montażu inline:Pomoc instrukcja zrozumienie DIV w x86 inline montażu

__asm__ (
    "divq %4" 
    : "=a" (q), "=d" (r) 
    : "0" (n0), "1" (n1), "rm" (d) 
); 

Tutaj zmienne q, r, n0, n1 i d to 64-bitowe liczby całkowite. Znam wystarczającą ilość zgromadzeń, aby zrozumieć, co się dzieje, ale są pewne szczegóły, których nie jestem pewien.

Co rozumiem:

Jesteśmy podzielenie zawartości rejestru RAX przez d, umieszczając w q iloraz i resztę umieszczając w r.

Co nie rozumiem

  1. Dlaczego istnieją trzy wejścia tutaj? Musimy tylko wprowadzić dywidendę i dzielnik, więc jakie zastosowanie może być dla 3 wejść?
  2. Nie mogę stwierdzić, które z danych wejściowych to dywidenda. Mówiąc ogólniej, nie widzę niczego, co faktycznie zostałoby załadowane do rejestru RAX, , więc skąd wie, co podzielić przez co?
+1

+1 dobrze sformatowane pytanie. Podoba mi się sekcja "Co rozumiem" i "czego nie rozumiem". –

Odpowiedz

4

W specyfikacji operandów wejściowych:

: "0" (n0), "1" (n1), "rm" (d) 

rejestrów "0" i "1" są zmuszeni do rax i rdx powodu specyfikacji wyjściowych:

: "=a" (q), "=d" (r) 

i rodziny div instrukcja chce licznik w RDX:RAX. Dzielnik może znajdować się w rejestrze ogólnego przeznaczenia (nie używanym w inny sposób - tj. Nie RAX lub RDX) ani w pamięci, która jest określona przez ograniczenie "rm". Rejestry RDX, RAX, a opera dzielnik składa się z 3 wejść.

To zakończy się wykonaniem podziału: n1:n0/d, gdzie n1:n0 jest ilością załadowaną do rdx:rax.

+0

czy rozumiem poprawnie, że można tego użyć do podzielenia 128-bitowej liczby całkowitej przez 64-bitową liczbę całkowitą? Wiedziałem, że jest to możliwe dla 32-bitowej wersji rejestru, ale nigdy nie myślałem, że będzie to również dotyczyło wersji 64-bitowej. –

+1

@Jens: To prawda.Należy jednak pamiętać, że (podobnie jak w przypadku mniejszych operacji podziału operandów), jeśli iloraz kończy się być zbyt dużym dla rejestru docelowego 'rax', otrzymasz wyjątek dzielenia. –

+1

Szybkim sposobem na sprawdzenie tego przypadku jest po prostu upewnienie się, że 'rdx' jest mniejsze niż dzielnik, w którym to przypadku podział jest bezpieczny. –

0

Jak prawidłowo obserwować rodzina div pracuje na stałych rejestrów a i d, rax i rdx dla divq. Rejestr a otrzymuje dane wejściowe z n0, które jest aliowane do rejestru 0., a mianowicie a. n1 to fałszywe wejście aliasingowane na d, prawdopodobnie tylko po to, aby ten rejestr nie był używany do innych celów.