1

Zastanawiam sie nad zastosowaniem relokacji w programie. W TA byl publikowany kod relokatora, ktory tez w nieco bardziej rozbudowanej formie, znalazl sie wewnatrz programow rezydentnych z pakietu QA.
Wydaje mi sie, z uwagi na jego uniwersalnosc (moze zostac uzyty zarowno pod SDX jak i kazdy inny system operacyjny), ze jest to rozwiazanie najlepsze, ale chcialbym sie upewnic w tym swoim wyborze i zapytac kolegow, czy istanieja jakies istotne przeslanki do wyboru relokacji pod SDX?
Mnie przychodzi na mysl jedynie skrocenie programu o kod relokatora, ktory jest obecny w systemie SDX (nawiasem mowiac, ciekawe na ile jest on zblizony do tego z TA i czy autor QA wzorowal sie w jakims stopniu na tym z SDX).
Natomiast co do oganiczen w tworzeniu kodu relokowanego sadze, ze sprawa ma sie podobnie (jestem swiezo po lekturze artykulu Qcyka z Seriousa na ten temat). Tzn. nie mozna korzystac z wartosci bezwzglednych adresow z obszaru relokowanego w trybie natychmiastowym, bo nie sposob by je relokator wlasciwie przeliczyl na wartosci prawidlowe po relokacji. Stosuje sie wiec w relokatorze z TA w zastepstwie, ale mysle, ze podobnie jest w SDX, z odwolan do tablic adresow przeliczanych przez relokator oddzielnie od kodu programu oraz danych stalych nie podlegajacych relokacji.
Jakie sa inne oganiczenia kodu relokacyjnego i czy sa one identyczne dla obu relokatorow?
To tyle, dziekuje z gory za wszelkie odpowiedzi.

ps. w tej chwili nie mam stalego dostepu do netu, stad bede odzywal sie znacznie rzadziej.

2

marok napisał/a:

Tzn. nie mozna korzystac z wartosci bezwzglednych adresow z obszaru relokowanego w trybie natychmiastowym

Wystarczy wyrównać adres ładowania do granicy strony i już można (bo zmieniają się tylko starsze bajty takich adresów).

KMK
? HEX$(6670358)

3

Przychodzi żaba do lekarza:
-panie doktorze, nie kumam.

Co zmienia wyrównanie adresu przy rozkazie
lda >adres
gdzie adres wskazuje na wnętrze relokowanego obszaru.

Aby odpackować teksty trzeba najpierw odpackować  program do ich odpackowywania - Energy #1

4

To, że młodszy bajt (lda <adres) pozostaje taki sam - nie trzeba relokatorowi informacji, gdzie jest.

KMK
? HEX$(6670358)

5

No a co ze starszym???

Aby odpackować teksty trzeba najpierw odpackować  program do ich odpackowywania - Energy #1

6 Ostatnio edytowany przez bori (2005-09-09 23:23:03)

zawsze mozna uzyskac adresowanie wgledem liczika rozkazow poprzez stos:

zamiast

  lda <dane
  sta vec
  lda >dane
  sta vec+1

mozna:

           
        php
        jsr $C0CE
tu:    tsx
        lda $FF,x
        clc
        adc #przesuniecie
        sta vec
        lda $100,x
        adc #0
        sta vec+1
dane:                   
                 
przesuniecie equ dane - tu + 1

7 Ostatnio edytowany przez drac030 (2005-09-10 00:18:20)

Jaskier napisał/a:

No a co ze starszym???

A starszy traktuje się tak samo, jak wszystkie inne starsze bajty wewnętrznych adresów tego pliku.

bori napisał/a:

zawsze mozna uzyskac adresowanie wgledem liczika rozkazow poprzez stos

Istnieje jednak prostsza, krótsza i o niebo bardziej elegancka metoda (zastosowana juz przez ICD w kodzie SpartaDOS X, na wypadek, gdyby ktoś myślał, że to wynalazek L.K. Avalonu, podobnie jak śmigłowiec, samolot itp.):

     lda dadr
     sta vec
     lda dadr+1
     sta vec+1
     ...
dadr .word dane
KMK
? HEX$(6670358)

8

Kurcze pieczone, kolejny po chińsku gada.

Po pierwsze, to lda $ff,x da tryb zerostronicowy i nic ze stosu nie przeczytasz.
Wymuszenie trybu długiego też nie jest w pełni poprawne, bo stos mógł się nam "zawinąć".
A najbardziej prawidłowo jest zapewne:
dex
lda $100,x
...
inx
lda $100,x
Po drugie, to przesunięcie może być większe od 255.
No i szybkość i czytelność tego rozwiązania jest dyskusyjna (lekko mówiąc).

Metoda użyta przez gości z Avalonu jest całkiem sensowna, bo zamiast stosowania takich karkołomnych sztuczek wystarczy pisać:
lda dane_addr
sta vec
lda dane_addr+1
sta vec+1

bądź:
mwa dane_addr vec
:D

Oczywiście to nie wystarczy aby program po zrelokowaniu dobrze działał. Musi być napisany tak, aby nigdzie nie zakładał, że np. jakaś tablica zaczyna się od początku strony. Trzeba też uważać na program Antica. No i pamięci ekranu w trybie graficznym praktycznie nie można relokować (chyba, że z wyrównaniem do 4KB). Ciekawe też rzeczy będą się działy jeśli program załadowany pod $8000 zrelokuje się pod $4000 i zacznie korzystać z banków. A jeśli stosujemy zmiany kolorów w linii za pomocą cyklowania, to też trzeba uważać, bo rozkazy skoku warunkowego i ładowanie indeksowe mogą się nagle wydłużyć o 1 cykl :)

Aby odpackować teksty trzeba najpierw odpackować  program do ich odpackowywania - Energy #1

9

Jaskier napisał/a:

Musi być napisany tak, aby nigdzie nie zakładał, że np. jakaś tablica zaczyna się od początku strony.

To chyba wynika z samej istoty sprawy, nieprawdaż?

KMK
? HEX$(6670358)

10

Pytał się o ograniczenia kodu relokacyjnego to odpowiadam :)

A mnie interesuje co innego:

Najpierw piszesz:
Wystarczy wyrównać adres ładowania do granicy strony i już można (bo zmieniają się tylko starsze bajty takich adresów).
A potem:
A starszy traktuje się tak samo, jak wszystkie inne starsze bajty wewnętrznych adresów tego pliku.

To w końcu można czy nie można???

No bo skąd relokator napotykając na rozkaz:
lda #$84
ma wiedzieć, że to nie jest takie zwykłe $84, ale starszy bajt jakiegoś adresu wewnątrz programu?

Aby odpackować teksty trzeba najpierw odpackować  program do ich odpackowywania - Energy #1

11 Ostatnio edytowany przez drac030 (2005-09-10 00:39:04)

Jaskier napisał/a:

Najpierw piszesz:
Wystarczy wyrównać adres ładowania do granicy strony i już można (bo zmieniają się tylko starsze bajty takich adresów).
A potem:
A starszy traktuje się tak samo, jak wszystkie inne starsze bajty wewnętrznych adresów tego pliku.

To w końcu można czy nie można???

Nie ma tu sprzeczności. Pismo mówi bowiem: można swobodnie i bez trudu korzystać z adresów bezpośrednich (natychmiastowych), gdy wyrówna się adres ładowania do granicy strony. Wtedy bowiem fixupowaniu podlegają tylko starsze bajty wewnętrznych adresów programu - a istotą rzeczy jest nie, że starsze czy nie starsze, ale że w każdym razie pojedyczne bajty programu podlegają fixupowaniu, i tym samym nie ma potrzeby dodawania z przeniesieniem całego adresu ładowania do wszystkich wewnętrznych adresów programu; a tylko starszy bajt adresu ładowania do wszystkich starszych bajtów jest dodawany i to bez przeniesienia.

Nie jest więc istotne, czy adres jest zapisany na dwóch kolejnych bajtach (lda adres / sta vec), czy na dwóch, ale nie kolejnych (lda #<adres / sta vec). Poniał? :)

Co więcej, jeśli założysz, że jakaś tablica ma ci się zaczynać od granicy stron, to taka relokacja sprawia, że ta tablica zawsze się od granicy stron będzie zaczynać.

No bo skąd relokator napotykając na rozkaz:
lda #$84
ma wiedzieć, że to nie jest takie zwykłe $84, ale starszy bajt jakiegoś adresu wewnątrz programu?

Z informacji o fixupach dołączonej do relokowanego pliku binarnego.

KMK
? HEX$(6670358)

12

Tobie chodzi chyba nie o ładowanie do granicy strony, a o relokację o wielokrotność 256 bajtów.
A jak generujesz tablicę fixupów?
No i dlaczego nie może ona obejmować zarówno starszych jak i młodszych bajtów adresów?
A w ogóle to ja proponuję zrobić relokator na podstawie źródeł QA. Ładujemy plik .asm i go assemblujemy od MEMLO.

Aby odpackować teksty trzeba najpierw odpackować  program do ich odpackowywania - Energy #1

13

Jaskier napisał/a:

A jak generujesz tablicę fixupów?

Banalnie prosto.

No i dlaczego nie może ona obejmować zarówno starszych jak i młodszych bajtów adresów?

Może, w zasadzie, ale ma to dwa mankamenty:

a) wydłuża tablicę fixupów (na oko dwukrotnie)

b) wymaga, żeby tąż tablicę fixupów generował kompilator

Punkt b) to problem bez wyjścia, kiedy kompilator, którego używasz, nie generuje kodu relokowalnego.

A w ogóle to ja proponuję zrobić relokator na podstawie źródeł QA. Ładujemy plik .asm i go assemblujemy od MEMLO.

A co, jeśli program ma np. 48k źródłówki i ponad 512 etykiet? :P

KMK
? HEX$(6670358)

14

Drac: a tak po za konkursem to gdzie leza te "Okolice Ukswordu" ?

Ja tak tylko z ciekawosci o 1:28 AM  ;)

15

W Warszawie :) Uksword to inaczej UKSW, czyli Uniwersytet im. Kardynała Stefana Wyszyńskiego, dawniej ATK.

KMK
? HEX$(6670358)

16

drac030 napisał/a:
Jaskier napisał/a:

A jak generujesz tablicę fixupów?

Banalnie prosto.

b) wymaga, żeby tąż tablicę fixupów generował kompilator

Dlaczego tablica starszych bajtów generuje się banalnie prosto, a do obu musi być zaprzęgnięty kompilator?

Aby odpackować teksty trzeba najpierw odpackować  program do ich odpackowywania - Energy #1

17

Dlatego, że jak masz lda #$84, wtedy tylko kompilator jest w stanie stwierdzić, czy to jest starszy bajt adresu, młodszy bajt adresu, czy w ogóle nie adres.

KMK
? HEX$(6670358)

18

A gdyby było do wyboru tylko starszy bajt adresu lub nie adres to można się bez kompilatora obyć?
Innymi słowy:
Pokaż mi jaka jest twoja metoda relokacji, która działa przy przesunięciach o x*256 bajtów a nie działa przy innych.

Aby odpackować teksty trzeba najpierw odpackować  program do ich odpackowywania - Energy #1

19

Bez kompilatora w ogóle trudno się obyć, ale rozumiem, że idzie o "bez kompilatora, który sam z siebie produkuje tablicę fixupów". A tych jest większość.

I jeśli idzie o "metodę relokacji", zakładam, że chodzi o metodę wytwarzania tablicy fixupów. Oto ona: kompilujesz program dwa razy, raz pod adres dajmy na to $2000, a drugi raz pod dajmy na to $3000 (może być $0100 i $0200 - non refert). Po czym porównujesz obydwie binarki i na podstawie różnic wytwarzasz tablicę fixupów.

Nie możesz tak zrobić dla pełnych adresów (kompilując np. jedną kopię pod $2000, a drugą pod $3001), bo fixupowanie musiałoby być dodawaniem z przeniesieniem, a nie jesteś w stanie zagwarantować, że dwa kolejne bajty, które dla generatora fixupów wyglądają na młodszy i starszy (z różnic adresów j.w.), należą rzeczywiście do tego samego adresu, a nie do dwóch różnych.

KMK
? HEX$(6670358)

20

Jaskier napisał/a:

Kurcze pieczone, kolejny po chińsku gada.

?

Po pierwsze, to lda $ff,x da tryb zerostronicowy i nic ze stosu nie przeczytasz.
Wymuszenie trybu długiego też nie jest w pełni poprawne, bo stos mógł się nam "zawinąć".

Mialem na mysli dluga instrukcje lda. Nie poprawny odczyt nastapilby kiedy wskaznik stosu mialby wartosc 0 co oznacza iz wczesniej nastapil stack overflow co nie powinno sie zdarzac.

A najbardziej prawidłowo jest zapewne:
dex
lda $100,x
...
inx
lda $100,x

Poprawki jak najbardziej sluszne, jesli juz bierzemy w/w przypadek.

Po drugie, to przesunięcie może być większe od 255.

To latwo rozszerzyc na cala przestrzen adresowa.

No i szybkość i czytelność tego rozwiązania jest dyskusyjna (lekko mówiąc).

Ale za to nie wymaga relokatora ;-), mozna go dowolnie przesuwac po pamieci razem z danymi

21 Ostatnio edytowany przez drac030 (2005-09-11 01:11:36)

bori napisał/a:

Ale za to nie wymaga relokatora ;-), mozna go dowolnie przesuwac po pamieci razem z danymi

Ale za to nie będzie ci działać, jeśli pod $C0CE nie ma tego, co zakładasz, że jest (a np. w Atari 400 i 800 nie ma tam nic). Ciekaw jestem, czy w QMEG-OS jest, bo w moim ROM-ie dla 65c816 nie ma z całą pewnością.

Zastanawiam się w ogóle, jaki sens ma ta kombinacja (php / jsr $c0ce). Zakładając nawet, że pod tym adresem jest rozkaz RTI. O ile mi wiadomo, JSR odkłada na stos adres powrotny pomniejszony o jeden, a przerwanie nie. Wobec tego JSR $C0CE odłoży na stos adres ostatniego bajtu argumentu rozkazu JSR, a RTI do tegoż ostatniego bajtu powróci (bo RTS zwiększa adres o 1, ale RTI nie). Po wykonaniu JSR (na standardowym ROM-ie) zostanie wykonany nie rozkaz TSX, ale CPY #$BA (gdzie $C0 to opcod CPY #, a $BA to opcod rozkazu TSX). Zastanawiam się, co ci to daje.

Domniemywam, że owo JSR ma wstawiać na stos adres bezwzględny kodu znajdującego się za JSR. Nawet jednak, gdyby tak było (a nie jest, patrz wyżej), to RTI ten adres ze stosu zdejmuje zwiększając przy tym wartość wskaźnika stosu. A pierwsze przerwanie - które może wystąpić zawsze, a więc natychmiast po wykonaniu się RTI również - ten adres skutecznie zamazuje. Toteż późniejszymi rozkazami (tsx, lda nnn,x itd.) zdejmujesz ze stosu wyłącznie śmieci, a program idzie w maliny.

KMK
? HEX$(6670358)

22

Ok, jest blad, faktycznie rti do rts rozni sie nie tylko odczytaniem statusu. Ale tez iz nie dodaje 1 do adresu ktory laduje do PC. Ale idea jest chyba jasna, wykonujemy jakakolwiek standartowa procedure (akutat wzialem fragment procedury PLARTI bo byla pierwsza w spisie :-)  i ze stosu zczytujemy PC dodajemy przesuniecie. Co do przerwan no faktycznie w atarce nie ma oddzielnego stosu dla nich i trzeba by je blokowac. Co nie zmienia faktu iz mozna napisac program calkowicie niezalezny od mniejsca polozenia w pamieci - bez koniecznosci jego zmiany przy przemieszczaniu. Ot i to co chcialem przekazac.

23

drac030 napisał/a:

Nie możesz tak zrobić dla pełnych adresów (kompilując np. jedną kopię pod $2000, a drugą pod $3001), bo fixupowanie musiałoby być dodawaniem z przeniesieniem, a nie jesteś w stanie zagwarantować, że dwa kolejne bajty, które dla generatora fixupów wyglądają na młodszy i starszy (z różnic adresów j.w.), należą rzeczywiście do tego samego adresu, a nie do dwóch różnych.

Dziwne, a mi się udało :D

http://jaskier.atari8.info/Relocator.zip

W katalog Program wsadzasz dowolny program do przerelokowania. Jedyne ograniczenie to kompilacja w jednym bloku, czyli brak rozkazów ORG (za wyjątkiem pierwszego oczywiście). Ten pierwszy też jest zresztą specjalny bo musi wyglądać tak:

    org ADDR

a wartość ADDR będzie już automatycznie wsadzana przez generator fixupów.

No i teraz przechodzimy do katalogu Generator i go uruchamiamy. Spowoduje to stworzenie w katalogu Program końcowego exeka zawierającego kompilowany program wraz z odpowiednim relokatorem i tablicą fixupów. Relokator przepisuje program pod memlo i uruchamia go od jego pierwszego bajtu.

Sprawdzałem go kilka razy na prostym przykładowym programie (wypisującym na ekranie kropkę) i działa z różnymi wartościami memlo. Wszelkie zauważone błędy prosze jednak natychmiast zgłaszać. Dziękuję za uwagę :)

Aby odpackować teksty trzeba najpierw odpackować  program do ich odpackowywania - Energy #1

24 Ostatnio edytowany przez drac030 (2005-09-11 13:16:38)

Jaskier napisał/a:

Dziwne, a mi się udało :D

Tak? A nie wykłada się aby na kombinacjach typu:

     lda #<adr1
     sta vec1
     lda #<adr2
     sta vec2
     lda #>adr1
     sta vec1+1
     lda #>adr2
     sta vec2+1

?

KMK
? HEX$(6670358)

25 Ostatnio edytowany przez drac030 (2005-09-12 22:43:08)

bori napisał/a:

Co do przerwan no faktycznie w atarce nie ma oddzielnego stosu dla nich i trzeba by je blokowac. Co nie zmienia faktu iz mozna napisac program calkowicie niezalezny od mniejsca polozenia w pamieci - bez koniecznosci jego zmiany przy przemieszczaniu. Ot i to co chcialem przekazac.

No dobrze, podsumujmy. Twoja propozycja:

1) zakłada użycie nielegalnego skoku do systemu
2) zajmuje sporo miejsca i jeszcze więcej cykli maszynowych
3) zakłada użycie danych, które są już zdjęte ze stosu
4) i z tego względu może działać tylko przy wyłączonych przerwaniach.

Sam przyznasz, że do podręcznika programowania to się raczej nie nadaje, chyba że jako antyprzykład :P

Co do tego stosu, można to spróbować zrobić inaczej. Mianowicie zapisujesz w spokojnym miejscu (np. na szóstej stronie) takie coś:

lea  pla
     clc
     adc #$01
     sta ret
     pla
     adc #$00
     sta ret+1
     jmp (ret)

Po wywołaniu JSR LEA w komórkach RET i RET+1 masz adres pierwszego rozkazu po JSR. Program nadal jednek nie jest w stu procentach niezależny od umieszczenia w pamięci, wydaje mi się, że takowy mozna stworzyć dopiero na 65C816 (mam tak np. rozpisany podprogram PRINTF, skompilowany kod można umieścić gdziekolwiek, np. w stringu BASIC-a, i zawsze działa).

EDIT: oczywiście popierdzieliła mi się kolejność bajtów na stosie. Teraz jest dobrze.

KMK
? HEX$(6670358)