15.03.2004
Architektura komputerów - oba tygodnie
Lista 3
Mamy 8-bitowy procesor z 8-bitową magistralą danych i przestrzenią adresową o architekturze akumulatorowo-rejestrowej oraz :
Lista instrukcji :
Składnia |
Funkcja |
adc src |
(COND≠0) => (C|A ← A + scr + C) |
sta dst |
dst ← A |
nand src |
A ← not (A & src) |
Zbiór rejestrów :
Rejestr |
Nazwa |
Funkcja |
R0 |
A |
Akumulator |
R1, ... ,R28 |
|
|
R29 |
COND |
Rejestr warunku |
R30 |
C |
R29[0] = C - bit przeniesienia |
R31 |
IP |
Wskaźnik rozkazów |
Tryby adresowania :
Tryb |
Składnia |
Dopuszczalne wystąpienie jako |
Natychmiastowy |
#wartość |
src |
Bezpośredni |
Rx |
src, dst |
Pośredni |
[Rx] |
src, dst |
|
Operacja |
Typ danej |
Dana |
Słowo |
O O |
X X |
D D D/R D/R D/R D/R D/R D/R |
zaproponuj kodowanie instrukcji takie aby maksymalna długość rozkazu wynosiła 2 bajty,
napisz fragmenty programów realizujące następujące funkcje :
sumę logiczną (or A, src),
NAND A //negowanie i umieszczenie w buforze
STA R0
NAND #0
NAND R1 //teraz ^R1 w A
NAND R0 // korzystając z praw de Morgana po tej operacji mamy sumę logiczną OR
sumę logiczną modulo 2 (xor A, src), src=R8
STA R2 //bufor
NAND A
NAND R8 //^(^A*R8)
STA R1
NAND #0 // same 1 w A
NAND R8 // ^R8
NAND R2 // ^(^R8*A)
NAND R1 // ^(^(^A*R8)*^(^R8*A))=^A*R8+^R8*A
wyzerowanie rejestru R1 (xor R1, R1),
NAND #0
NAND R1 //R1 w akumulatorze
xor A,R1 //zdefiniowany wyzej
STA R1
//albo prościej
NAND #0
NAND A
STA R1 //same 0 w R1
wpisanie wartości val do rejestru R2 (mov R2, val),
NAND #0
NAND #val
NAND A
STA R2
wykonanie bezwzględnego skoku bezwarunkowego pod podany adres (jmp adr),
NAND #0
NAND #adr
NAND A
STA IP
wykonanie względnego skoku warunkowego gdy ustawiona jest flaga C (jc adr),
NAND #0 //1111 1111
NAND #01H //1111 1110
NAND A //0000 0001
NAND C //1111 111^C
NAND A //0000 000C
STA COND
NAND #0
NAND A
STA C //wyzeruj C
NAND #0
NAND IP
NAND A
ADC adr
STA IP
załadowanie akumulatora wartością z komórki pamięci wskazanej przez src (mov A, [src]),
NAND #0
NAND [src]
NAND A
zwiększenie akumulatora o jeden (inc A),
STA R1
NAND #0 //1111 1111
NAND #0FEH //0000 0001
STA C
STA COND
NAND #0
NAND A
ADC R1
zmniejszenie akumulatora o jeden (dec A),
STA R1
NAND #0
NAND A
STA C
NAND A
STA COND
ADC R1
pętlę wykonującą się Rx razy
NAND #0
NAND #45H
NAND A
STA R5 //R5 licznikiem
NAND #0 //przygotowanie adresu powrotu
NAND IP //pobranie stanu wskaźnika
NAND A
STA R3
……
……
……
NAND #0
NAND A
STA C //zerowanie przeniesienia
NAND A
NAND R5
NAND A
DEC A
STA COND
NAND #0
NAND #3 //o ile adres musi być większy,
żeby przeskoczyć przepisywanie IP
NAND A
ADC R3
NOP
NOP
STA IP //powrót na górę
…….
NOP
odkładanie i zdejmowanie zawartości akumulatora na/ze stosu (przyjmij rejestr R28 jako wskaźnik stosu),
//R28 wskazuje szczyt stosu
NAND #0
NAND A
STA R28
………
PUSH:
STA buff //miejsce jako bufor
NAND #0
NAND R28
NAND A
INC A
STA R28
NAND #0
NAND buff
NAND A
STA [R28]
RET
POP:
NAND #0
NAND [R28]
NAND A
STA buff
NAND #0
NAND R28
NAND A
DEC A
STA R28
RET
wywołania i powrotu z podprocedury.
CALL:
NAND #0
STA COND
NAND A
STA C
NAND A
NAND IP
NAND A
ADC #przes //przes takie, aby ip wskazywał na rozkaz za CALL
PUSH A
JMP adr //adres podprocedury
RET:
POP A
STA IP
2. Mamy 8-bitowy procesor z 8-bitową magistralą danych i przestrzenią adresową, o architekturze rejestrowej oraz :
Lista instrukcji :
Składnia |
Funkcja |
adc Rk, Rn, Rm |
(COND≠0) => (C| Rm ← Rk + Rn + C) |
st Rk, Rm |
[Rm] ← Rk |
ld Rk, Rm |
Rm ← [Rk] |
nand Rk, Rn, Rm |
Rm ← not (Rn & Rk) |
Zbiór rejestrów :
Rejestr |
Nazwa |
Funkcja |
R0, ... ,R28 |
|
|
R29 |
COND |
Rejestr warunku |
R30 |
C |
R29[0] = C - bit przeniesienia |
R31 |
IP |
Wskaźnik rozkazów |
Tryby adresowania :
Tryb |
Składnia |
Dopuszczalne wystąpienie jako |
Natychmiastowy |
#wartość |
src |
Bezpośredni |
Rx |
src, dst |
Pośredni |
[Rx] |
src, dst |
zaproponuj kodowanie instrukcji takie aby maksymalna długość rozkazu była jak najkrótsza
operacja |
dst [Rm] |
|
|
src [Rk] |
|
src [Rn] |
|
|
OO |
RRRRR |
X |
|
RRRRR |
XXX |
|
RRRRR |
XXX |
napisz fragmenty programów realizujące następujące funkcje :
sumę logiczną (or Rk, Rn, Rm),
NAND Rm, Rm, Rm
NAND Rn, Rn, Rn,
NAND Rm, Rn, Rz
NAND Rz, Rz, Rz
NAND Rk, Rk, Rk
NAND Rk, Rz, Rm
sumę logiczną modulo 2 (xor Rk, Rn, Rm),
wpisanie wartości val do rejestru (mov val, Rm),
NAND R3, R3, R4
NAND R4, R3, R3
NAND R3, R3, R4 //wyzerowanie rejestru
wykonanie bezwzględnego skoku bezwarunkowego pod podany adres (jmp adr),
NAND #0
NAND #adr
NAND A
STA IP
wykonanie względnego skoku warunkowego gdy ustawiona jest flaga C (jc adr),
zwiększenie rejestru o jeden (inc Rk, Rm),
zmniejszenie rejestru o jeden (dec Rk, Rm),
pętlę wykonującą się Rx razy
odkładanie i zdejmowanie zawartości akumulatora na/ze stosu (przyjmij rejestr R28 jako wskaźnik stosu),
wywołania i powrotu z podprocedury.
3. Dysponując instrukcjami procesora RISC (o 32 rejestrach R0-R31):
Składnia |
Funkcja |
sub Rk, Rm, Rn |
Rn ← Rk - Rm - różnica w U2 |
or Rk, Rm, Rn |
Rn ← Rk or Rm - suma logiczna |
not Rk, Rn |
Rn ← not( Rk ) - zaprzeczenie logiczne |
oraz wiedząc, że rejestr R0 jest tylko odczytywalny i zawiera stałą zero zasymuluj następujące instrukcje :
neg Rk, Rm - negacja liczby w U2
NOT R3, R2 //negacja liczby w R2
NOT R0, R4 //same 1 w R4 (-1 U2)
SUB R2, R4, R3 // liczba - (-1)=liczba+1
add Rk, Rm, Rn - suma liczb w U2
NEG R3
SUB R4, R3, R2 //wynik dodawania w R2 R4+R3=R2
and Rk, Rm, Rn - iloczyn logiczny
NOT R3, R4
NOT R5, R1
OR R4, R1, R2
NOT R2, R2 // R2 = R3 and R5
move Rk, Rm - przepisanie bajtu pomiędzy rejestrami
NOT R3, R4
NOT R4, R4
4. Dysponując instrukcjami z zadania 3 oraz instrukcją skoku warunkowego :
br Rk, adr - skok pod adres adr jeśli rejestr Rk≠0
napisz program wyliczający :
wartość silni dla argumentu podanego w R6
BR R6, licz
MOVE R0, R8
NOT R0, R7
NEG R7
ADD R8, R7, R8
BR R7, koniec
licz:
MOVE R6, R8
MOVE R6, R9
NOT R0, R7 //(-1) w R7
ADD R9, R7, R9
MOVE R9, R10
mnożenie:
// mnożenie
//wynik R8=R8*R9
MOVE R6, R9 // licznik w R9
ADD R8, R8, R8 //dodawanie w mnożeniu
ADD R9, R7, R9 //dekrementacja licznika
BR R9, mnożenie
ADD R10, R7, R10
MOVE R10, R9
BR R9, mnożenie
koniec:
k-tą liczbę Fibonacciego dla k podanego w rejestrze R7
NOT R0, R8
NEG R8,R8 //k-1; na końcu wynik
MOVE R7,R6
MOVE R0,R9 //k-2
BR R7, oblicz
BR R8, koniec
oblicz:
MOVE R8, R10
ADD R8, R9, R8
MOVE R10,R9
NOT R0, R10
ADD R10, R6 //dekrementacja
BR R6, oblicz
koniec: //wynik w R8
end
Program dla 8086 odejmujący dwie liczby. Jeśli wynik dodatni, to nie robi nic, Jeśli ujemny to do wyniku dodaje 1.
CLC
MOV AL,5
SBB AL,8
ADC AL,0
END