forum speccy.pl
ZX Spectrum => PROGRAMOWANIE => Wątek zaczęty przez: gregoryi w 2016.11.16, 09:28:43
-
Witam.
Nie mogę załapać dlaczego nie działa.
Prośba o wyprostowanie mnie.
Swego czasu napisałem sobie program rysujący flagi (bardzo prosty).
Potem przerobiłem go na asemblera, a teraz chciałem zoptymalizować.
W starym skrypcie wszystkie pola flag były pisane ciurkiem, znaczy każde pole miało swój kod.
Chciałbym wykorzystać zmienne np. kolor1, kolor2, il_kolumn, il_wierszy, ... itp. skróci program.
To co na chwilę obecną testuję
org 30000
call procedura1
ret
org 60000
procedura1:
ld hl,$5801
ld e,31
looppolbi11:
push hl
ld b,11
looppolbi12:
ld (hl),kolor1 ;linia występowania błędu
ld d,b
ld b,32
loophlpolbi11:
inc hl
djnz loophlpolbi11
ld b,d
djnz looppolbi12
pop hl
inc hl
ld b,e
dec b
ld e,b
djnz looppolbi11
ret
kolor1: db 120
Używam ZXSpin (w nim asemblera)
Występuje błąd: Byte value out of range
Natomiast jak zrobię tak:
org 30000
ld a,(kolor1)
call procedura1
ret
org 60000
procedura1:
ld hl,$5801
ld e,31
looppolbi11:
push hl
ld b,11
looppolbi12:
ld (hl),a ;błędu już nie ma
ld d,b
ld b,32
loophlpolbi11:
inc hl
djnz loophlpolbi11
ld b,d
djnz looppolbi12
pop hl
inc hl
ld b,e
dec b
ld e,b
djnz looppolbi11
ret
Gdzie popełniam błąd. Chcę przekazywać do procedury więcej parametrów, czy to w ogóle możliwe?
-
kolor1 to szesnastobitowy adres a nie ośmiobitowa wartość.
wartości to przez equ (http://pasmo.speccy.org/pasmodoc.html#direqu)...
-
Dokadnie, jak pisze steev.
ld (hl),kolor1
a pewnie chciales
ld (hl),(kolor1 )
tyle ze tak sie nie da. Mozna za to
ld a, (kolor)
ld (hl), a
pisze z glowy. I przepraszam za brak polskich ogonkow. cos mi windows strajkuje.
-
Cześć.
A więc tak, masz definicję komórki pamięci:
kolor1: db 120
a następnie chcesz zawartość tej komórki pamięci zapisać do innej komórki pamięci:
ld (hl),kolor1 ;linia występowania błędu
i to jest złe, ponieważ kolor1 to jakiś adres w pamięci, który jest 16 bitowy, zatem kompilator próbuje skompilować coś takiego:
ld (hl),$xxxx (wartość 16 bitowa a nie 8bit).
Tobie zależy na danej, która znajduje się pod tym adresem, zatem powinieneś zrobić tak:
ld a,(kolor1)
ld (hl),a
-
Lub (jeśli kolor1 jest stałą) to na początku programu
kolor1 equ 120
(składnia może się zmieniać w zależności od stosowanego asemblera, trzeba sprawdzić w dokumentacji)
i wtedy można stosować taką etykietkę zamiast liczby (np. ld a,kolor1)
-
Próbowałem również zrobić tak:
ld (hl), (kolor1) ; wystąpił błąd invalid combination of opcode and operands
Zrobiłem tak:
org 30000; flaga polski
kolor equ 120
il_k equ 31
il_w equ 11
licznik equ 32
pocz equ $5801
call procedura
kolor equ 80
il_k equ 31
il_w equ 11
licznik equ 32
pocz equ $5961
call procedura
ret
org 60000
procedura:
ld hl,pocz ;adres poczatkowy atrbutow
ld e,il_k ;ilosc kolumn
looppolbi11:
push hl ;zachowanie adresu atrybutow
ld b,il_w ;ilosc wierszy
looppolbi12:
ld (hl),kolor ;wyswietlenie koloru white-bright w adres atrybutu
ld d,b ;zachowanie pozycji ilosci wierszy
ld b,licznik ;licznik petli do djnz
loophlpolbi11:
inc hl ;zwiekszanie adresu atrybutu o 1
djnz loophlpolbi11
ld b,d ;wystawienie licznika petli do djnz
djnz looppolbi12
pop hl ;wstawienie adresu atrybutow
inc hl
ld b,e
dec b
ld e,b
djnz looppolbi11
ret
I otrzymuję podwójną definicję zmiennych.
Jak w asemblerze do wcześniej zdefiniowanych zmiennych podstawić wartość?
-
Jak w asemblerze do wcześniej zdefiniowanych zmiennych podstawić wartość?
Tak naprawdę tu nie ma zmiennych. W trakcie definiowania na przykład:
moja_zmienna defb 128
w pewnym miejscu pamięci przypisujesz wartość 128, a to miejsce otrzymuje label (nie wiem jak to jest po polsku).
Do tego miejsca w pamięci można się odwołać na przykład:
ld a, 64
ld (moja_zmienna), a
przypisując w to samo miejsce w pamięciu wartość 64. Natomiast
ld hl, moja_zmienna
powoduje przypisanie do rejestru HL adresu tej "zmiennej". I dalej można na przykład:
ld (hl), 64
co również spowoduje przypisanie wartości 64 w odpowiednie miejsce w pamięci.
-
Po polsku Label to Etykieta.
-
Ja tylko chciałem zwrócić uwagę że nie ma w Z80 nie takiego adresowania jak poniżej:
ld (moja_zmienna), 64
trzeba to zrobić za pomocą rejestrów, to znaczy albo tak:
ld a,64
ld (moja_zmienna),a
albo tak:
ld hl,moja_zmienna
ld (hl),64
-
Oczywiście masz rację, już poprawiłem. :-[
-
org 30000
ld a,120
ld (kolor),a
ld a,31
ld (il_k),a
ld a,11
ld (il_w),a
ld a,32
ld (licznik),a
ld de,$5801
ld (pocz),de
call procedura
ld a,80
ld (kolor),a
ld a,31
ld (il_k),a
ld a,11
ld (il_w),a
ld a,32
ld (licznik),a
ld de,$5961
ld (pocz),de
call procedura
ret
org 30070
ld a,80
ld (kolor),a
ld a,31
ld (il_k),a
ld a,11
ld (il_w),a
ld a,32
ld (licznik),a
ld de,$5801
ld (pocz),de
call procedura
ld a,120
ld (kolor),a
ld a,31
ld (il_k),a
ld a,11
ld (il_w),a
ld a,32
ld (licznik),a
ld de,$5961
ld (pocz),de
call procedura
ret
org 60000
procedura:
ld hl,(pocz) ;adres poczatkowy atrbutow
ld a,(il_k)
ld e,a ;ilosc kolumn
looppolbi11:
push hl ;zachowanie adresu atrybutow
ld a,(il_w)
ld b,a ;ilosc wierszy
looppolbi12:
ld a,(kolor)
ld (hl),a ;wyswietlenie koloru white-bright w adres atrybutu
ld d,b
ld a,(licznik) ;zachowanie pozycji ilosci wierszy
ld b,a ;licznik petli do djnz
loophlpolbi11:
inc hl ;zwiekszanie adresu atrybutu o 1
djnz loophlpolbi11
ld b,d ;wystawienie licznika petli do djnz
djnz looppolbi12
pop hl ;wstawienie adresu atrybutow
inc hl
ld b,e
dec b
ld e,b
djnz looppolbi11
ret
kolor db 0
il_k db 0
il_w db 0
licznik db 0
pocz db 0
To działa ale myślałem, że można prościej
Bo nie działa mi:
ld (zmienne),wartość
i
ld e,(il_k)
Na przemian flaga polski flaga monako w ramach testów czy nie rozjedzie się.
Jak będę w domu to podeślę stary program.
-
Tutaj jest bardzo wygodna tabelka, która pokazuje gdzie można zrobić LoaD.
http://z80-heaven.wikidot.com/instructions-set:ld (http://z80-heaven.wikidot.com/instructions-set:ld)
-
Tutaj też http://speccy.pl/wiki/index.php?title=Rozkaz_LD (http://speccy.pl/wiki/index.php?title=Rozkaz_LD)
-
Ja to wszystko rozumiem.
Tylko nie mogę pojąć dlaczego
mogę zrobić tak
ld a,(zmienna)
a nie mogę zrobić
ld e,(zmienna)
Trochę jest to zaskakujące.
Natomiast definiowanie zmiennych (etykiet):
zmienna db wartość
nie określa typu czy jest to 8-bit czy 16-bit, dlatego występuje błąd "value out of range".
Przykładem może być zmienna kolor (8-bit) a zmienna pocz (16-bit).
Prawdopodobnie akumulator obcina wartość do 8-bit.
Z moich obserwacji.
-
Nie możesz tak zrobić bo rejestr E nie jest rejestrem uniwersalnym, tak jak A. Dla rejestrów innych niż A,I,R,F dozwolone są przypisania następujące przypisania wartości (na przykładzie rejestru E):
LD E,liczba 8bitowa
LD E,inny_rejestr_8bit
LD E,(HL)
LD E,(IX+n)
LD E,(IY+n)
-
Ja to wszystko rozumiem.
Tylko nie mogę pojąć dlaczego
mogę zrobić tak
ld a,(zmienna)
a nie mogę zrobić
ld e,(zmienna)
Trochę jest to zaskakujące.
Moim zdaniem nie jest zaskakujące. Rejestr A to tzw. akumulator - rejestr wyróżniony. Oferuje on więcej operacji na swojej zawartości, niż inne rejestry. Jest to konstrukcyjna zaszłość jeszcze z epoki kalkulatorów, która spokojnie przetrwała burzliwy rozwój mikroprocesorów, począwszy od Intel 4004, 4040, 8008, potem 8080 i dochodzimy do Z80.
Natomiast definiowanie zmiennych (etykiet):
zmienna db wartość
nie określa typu czy jest to 8-bit czy 16-bit, dlatego występuje błąd "value out of range".
Przykładem może być zmienna kolor (8-bit) a zmienna pocz (16-bit).
Nie wiem jak dziś, kiedyś w assemblerze było rozróżnienie na DB (8-bit) i DW (16-bit), odpowiednio "Declare Byte" i "Declare Word".
Być może nowsze assemblery rozpoznają większe wartości/łańcuchy po "DB" i rezerwują większą liczbę bajtów, nie wiem.
Prawdopodobnie akumulator obcina wartość do 8-bit.
Z moich obserwacji.
Skoro akumulator jest 8-bitowy, to nie może robić inaczej - nie przechowa więcej bitów ;)
-
Nie wiem jak dziś, kiedyś w assemblerze było rozróżnienie na DB (8-bit) i DW (16-bit), odpowiednio "Declare Byte" i "Declare Word".
Być może nowsze assemblery rozpoznają większe wartości/łańcuchy po "DB" i rezerwują większą liczbę bajtów, nie wiem.
Myślę, że zachowanie jest tutaj nieokreślone i zależne od widzimisia twórcy narzędzia.
Np. asembler z sdcc zapisuje wtedy jedynie młodsze bajty:
1 .module test
2 .optsdcc -mz80
3 .area DATA
4
0000 01 02 03 04 05 06 5 bajty: .db 1,2,3,4,5,6,0x1122,0x3344,0x5566
22 44 66
0009 07 00 08 00 09 00 6 slowa: .dw 7,8,9,0xa,0xb,0xc,0x7788,0x99aa,0xbbcc
0A 00 0B 00 0C 00
88 77 AA 99 CC BB
-
O, i ma to logiczny sens. Każdy argument DB powinien być 8-bitowy, ale może być tych argumentów więcej (rozdzielonych przecinkami) - ale wszystkie pozostają 8-bitowe, więc jak coś "wystaje" poza 8 bitów, jest ucinane.
-
Obiecany pliczek z flagami.
-
Ciekawy program ;-)