Kod operacji Intel BCD
Kody operacji Intel BCD to zestaw sześciu instrukcji x86 , które działają na liczbach dziesiętnych zakodowanych binarnie . Podstawa używana do reprezentacji liczb w procesorach x86 to 2. Nazywa się to binarnym systemem liczbowym . Jednak procesory x86 mają ograniczoną obsługę dziesiętnego systemu liczbowego .
Ponadto część x87 obsługuje unikalny 18-cyfrowy (dziesięciobajtowy) format BCD, który można załadować do rejestrów zmiennoprzecinkowych i przechowywać z nich, skąd można wykonywać zwykłe obliczenia FP.
Instrukcje BCD dotyczące liczb całkowitych nie są już obsługiwane w trybie długim .
Stosowanie
Reprezentacja liczbowa
Liczby BCD mogą być reprezentowane na dwa sposoby w rejestrach całkowitych: upakowane dziesiętne i rozpakowane dziesiętne.
-
Pakowane (4 bity)
- W spakowanej reprezentacji dziesiętnej cyfra dziesiętna jest przechowywana w jednym półbaju .
- Wartości od 10 do 15 nie są używane.
-
Rozpakowane (8 bitów)
- W rozpakowanej reprezentacji dziesiętnej cyfra dziesiętna jest przechowywana w jednym bajcie .
- Wartości od 10 do 255 nie są używane.
- Górny półbajt jest ignorowany i może wynosić zero lub pierwszy półbajt dla znaku ASCII (wartość 3).
Ogólnie przyjmuje się, że numery BCD są przechowywane w najniższym bajcie rejestru, np. AL; operacje na rozpakowanych liczbach BCD wymagają najmniej znaczącej cyfry w najniższym bajcie rejestru, np. AL, i najbardziej znaczącej cyfry w drugim najniższym bajcie, np. AH.
Dodawanie
można dodać tylko liczby dziesiętne od 0 do 99 .
Najpierw liczby są dodawane jak zwykle za pomocą add (lub adc , jeśli potrzebujesz flagi przenoszenia ). Procesor ustawi flagę dostosowania, jeśli suma obu niższych półbajtów wynosi 16 lub więcej, a flagę przeniesienia, jeśli suma obu bajtów wynosi 256 lub więcej.
Następnie wynik jest korygowany w zależności od reprezentacji liczbowej.
-
zapakowane
- Wynik jest korygowany za pomocą daa (korekta dziesiętna po dodaniu): Jeśli najmniej znaczący półbajt wyniku wynosi 10 lub więcej lub jeśli ustawiona jest flaga dostosowania, to procesor dodaje 6 do wyniku i odrzuca nadmiar półbajtu.
- Następnie, jeśli najbardziej znaczący półbajt wyniku wynosi 10 lub więcej lub jeśli flaga przenoszenia jest ustawiona, procesor dodaje 96 (6 razy 16) do wyniku i ustawia flagę przenoszenia.
-
Rozpakowany
- Wynik jest korygowany za pomocą aaa (korekta ASCII po dodaniu): Jeśli najmniej znaczący półbajt wyniku wynosi 10 lub więcej, to procesor dodaje do niego 6 i odrzuca wszelkie przepełnienie półbajtu i zapisuje go w najmniej znaczącym bajcie.
- Najbardziej znaczący bajt jest zwiększany.
- Zauważ, że w tym momencie najbardziej znaczący bajt może nie zawierać prawidłowej liczby dziesiętnej.
Odejmowanie
Tylko liczby dziesiętne od 0 do 99 można odjąć bezpośrednio. Najpierw liczby są odejmowane jak zwykle za pomocą sub (lub sbb , jeśli potrzebujesz flagi przenoszenia). Procesor ustawi flagę dostosowania, jeśli pożyczka wystąpiła w najmniej znaczącym półbajcie, oraz flagę przeniesienia, jeśli pożyczka wystąpiła w najbardziej znaczącym półbasie.
-
zapakowane
- Wynik jest korygowany za pomocą das (korekta dziesiętna po odejmowaniu): Jeśli najmniej znaczący półbajt wyniku wynosi 10 lub więcej lub jeśli ustawiona jest flaga dostosowania, procesor odejmuje 6 od wyniku.
- Następnie, jeśli najbardziej znaczący półbajt wyniku wynosi 10 lub więcej lub jeśli flaga przenoszenia jest ustawiona, procesor odejmuje 96 (6 razy 16) od wyniku i ustawia flagę przenoszenia.
-
Rozpakowany
- Wynik jest korygowany za pomocą aas (skorygowanie ASCII po odejmowaniu): Jeśli najmniej znaczący półbajt wyniku wynosi 10 lub więcej, procesor odejmuje od niego 6 i zapisuje w najmniej znaczącym bajcie.
- Najbardziej znaczący bajt jest zmniejszany.
- Zauważ, że w tym momencie najbardziej znaczący bajt może nie zawierać prawidłowej liczby dziesiętnej.
Mnożenie
Obsługiwana jest tylko reprezentacja rozpakowana. Można pomnożyć tylko dwie liczby jednocyfrowe .
Najpierw cyfry są mnożone jak zwykle za pomocą mul .
Następnie wynik jest korygowany za pomocą aam (dostosowanie ASCII do mnożenia): Procesor dzieli wynik przez dziesięć, zapisując iloraz (tylko część całkowitą ) w najbardziej znaczącym bajcie wyniku, a resztę w najmniej znaczącym bajcie wyniku .
Dział
Obsługiwana jest tylko reprezentacja rozpakowana. Argumenty muszą mieścić się w zakresie od 0 do 99.
Najpierw operandy są konwertowane na normalną reprezentację binarną za pomocą aad (dopasowanie ASCII przed dzieleniem): Procesor konwertuje liczby, mnożąc najbardziej znaczący bajt przez 10 i dodając najmniej znaczący bajt. Iloraz i reszta z dzielenia są uzyskiwane jak zwykle za pomocą div i będą obecne w normalnej reprezentacji binarnej.
w x87
Koprocesor x87 obsługuje BCD w postaci pary instrukcji ładowania (FBLD) oraz instrukcji typu store-and-pop (FBSTP). Pierwszy ładuje 80-bitową liczbę całkowitą BCD do FPU, podczas gdy drugi zapisuje wartość FPU jako 80-bitową liczbę całkowitą do pamięci. Wewnątrz FPU wartości są przechowywane jako zwykłe zmiennoprzecinkowe x87 o rozszerzonej precyzji . W przeciwieństwie do wersji z liczbami całkowitymi, dwie instrukcje pozostają dostępne w trybie długim.
Format 80-bitowy dzieli się na:
79 | 78 .. 72 | 71 .. 0 |
---|---|---|
Podpisać | nieużywane (0) | 18 spakowanych cyfr |
Istnieje specjalna „nieokreślona” wartość zakodowana jako FFFFC000000000000000h.
Aplikacja
dziesiętne kodowane binarnie (BCD) są używane do przechowywania liczb dziesiętnych, zwłaszcza w oprogramowaniu finansowym.
kody operacyjne zapewniają podstawową obsługę BCD x86.
Alternatywy
Dodawanie numerów BCD przy użyciu tych opkodów jest złożonym zadaniem i wymaga wielu instrukcji, aby dodać nawet skromne liczby. Może również wymagać dużej ilości pamięci. Jeśli wykonujesz tylko obliczenia na liczbach całkowitych, wszystkie obliczenia na liczbach całkowitych są dokładne, więc podstawa reprezentacji liczbowej nie jest ważna dla dokładności. Na procesorze x86 obliczenia z liczbami binarnymi są zwykle dużo szybsze niż te same obliczenia z liczbami BCD.