MOS Technology 6502: Różnice pomiędzy wersjami

[wersja przejrzana][wersja nieprzejrzana]
Usunięta treść Dodana treść
→‎Opis: styl + usunięte brednie o adresowaniu pamięci poza stroną zerową; specjaliści z pl.wiki, psiakość :/
→‎Obliczenia: nie potrafisz, nie pchaj się na afisz...
Linia 17:
* [[MOS Technology 6510|MOS 6510]]
 
== ObliczeniaArytmetyka ==
Mikroprocesor 6502 może bezpośrednio wykonywać m.in. takie obliczenia arytmetyczne jak dodawanie oraz odejmowanie (również dziesiętne), nie jest jednak wyposażony w rozkazy dzielenia i mnożenia. Dzielenie i mnożenie (zarówno liczb binarnych jak i dziesiętnych) jest jednak, oczywiście, wykonalne.
Mikroprocesor 6502 mógł wykonywać m.in. takie instrukcje jak dodawanie oraz odejmowanie, nie był jednak wyposażony w funkcję dzielenia i mnożenia. Pomimo tego, dzięki istnieniu trzech rejestrów, dało się wykonywać działania, do których teoretycznie architektura procesora się nie nadawała. W przypadku ilorazu, dokonywało się tego poprzez zliczanie liczby różnic odjemnej zawartej w Akumulatorze i odejmnika zaadresowanego w dowolny sposób - bezpośredni lub poprzez wczytanie wartości z pamięci, bądź z rejestru pomocniczego. Za kalkulowanie liczby różnic odpowiadał dowolny z rejestrów pomocniczych (X lub Y). Pod koniec dzielenia, wartość w rejestrze pomocniczym określała wynik dzielenia, w Akumulatorze pozostawała natomiast reszta z ilorazu. Przykładowy kod źródłowy programu dzielącego liczbę z Akumulatora przez 2 może wyglądać tak:
 
Jeśli mnożnik lub dzielnik jest którąś z potęg liczby 2, stosuje się przesunięcia i obroty bitowe, odpowiednio w lewo (rozkazy ASL i ROL) lub w prawo (rozkazy LSR i ROR). Dzielenie przez 2 ośmiobitowej liczby znajdującej się w akumulatorze wygląda więc tak:
 
<source lang="asm">
LSR
LDX #0 ; Zerowanie wartości w rejestrze X
</source>
DZIELENIE
 
CMP #2 ; Sprawdzanie czy od wartości w Akumulatorze może zostać odjęta liczba 2
Natomiast dzielenie 16-bitowej liczby znajdującej się w pamięci wygląda tak:
BMI KONIEC ; Jeśli po odjęciu liczby 2 wartość w Akumulatorze byłaby ujemna, następuje przeskok do etykiety KONIEC
 
SEC ; Ustawienie flagi Carry
<source lang="asm">
SBC #2 ; Odjęcie liczby 2 od wartości w Akumulatorze
LSR ZMIENNA+1
INX ; Zwiększenie wartości w rejestrze X o jeden
ROR ZMIENNA
JMP DZIELENIE ; Skok do etykiety DZIELENIE
</source>
KONIEC
 
; (...)
Dzielniki i mnożniki inne od potęg dwójki wymagają zastosowania procedury złożonej z wielu rozkazów. Dzielenie można w teorii wykonywać metodą wielokrotnego odejmowania (wynikiem jest wtedy liczba odejmowań, resztą - wynik ostatniego odejmowania), a mnożenie, analogicznie, metodą wielokrotnego dodawania. Są to jednak sposoby bardzo nieefektywne i z tego powodu nie znajdują praktycznego zastosowania.
 
W praktyce stosuje się procedury polegające na połączeniu dzieleń (lub mnożeń) przez dwa oraz odejmowań (lub dodawań). Zapewnia to przeprowadzenie obliczeń w rozsądnym czasie (w granicach 500-1000 cykli zegara CPU). Poniżej przykładowa procedura mnożenia dwóch liczb całkowitych, 16-bitowych, bez znaku; zakończenie procedury z ustawionym znacznikiem C sygnalizuje przepełnienie, czterobajtowy wnik zastepuje w pamięci MNOŻNĄ:
 
<source lang="asm">
 
MNOZNA .DS 4
MNOZNIK .DS 2
_POMOC .DS 2
 
MUL16 CLC
LDA MNOZNA ;gdy mnoznik albo mnozna jest zerem
ORA MNOZNA+1 ;to zerem jest rowniez wynik.
BEQ _CLR
 
LDA MNOZNIK
ORA MNOZNIK+1
BEQ _CLR
 
LDA MNOZNA ;kopiujemy mnozna do rejestru pomocniczego
STA _POMOC
LDA MNOZNA+1
STA _POMOC+1
 
JSR _CLR ;zerujemy bajty wyniku
 
LDX #16
_MUL LSR MNOZNIK+1 ;glowna petla
ROR MNOZNIK
BCC _NOAD
 
CLC
LDA MNOZNA+2
ADC _POMOC
STA MNOZNA+2
LDA MNOZNA+3
ADC _POMOC+1
STA MNOZNA+3
BCS _EXIT
 
_NOAD LSR MNOZNA+3
ROR MNOZNA+2
ROR MNOZNA+1
ROR MNOZNA
DEX
BNE _MUL
CLC
_EXIT RTS
 
_CLR LDX #$03
LDA #$00
_CL STA MNOZNA,X
DEX
BPL _CL
RTS
</source>