Autor Wątek: Amstrad Basic  (Przeczytany 20462 razy)

matofesi

  • *****
  • Wiadomości: 2048
  • Miejsce pobytu:
    Toruń/Poland
Odp: Amstrad Basic
« Odpowiedź #15 dnia: 2015.11.18, 15:41:16 »
Co dokładnie robi instrukcja CALL &4000,&5000 ?

Czy to jest wywołanie procedury pod &4000 z wartością &5000 w rejestrze (którym?)

Hmmm... http://bfy.tw/2qqC ;)

Pierwsze dwie pozycje to ogólny i bardziej szczegółowy opis Locomotive BASICa a trzecia to techniczny opis jak wywołuje się kod maszynowy z tegoż i jak przekazywane są parametry.

ZbyniuR

  • *****
  • Wiadomości: 3333
  • Miejsce pobytu:
    Carlisle w UK
  • CPC AGA PSX
Odp: Amstrad Basic
« Odpowiedź #16 dnia: 2015.11.18, 15:44:22 »
Pierwszy parametr to adres spod jakiego binarkę ten CALL uruchamia, a drugi to już musi wynikać z tej binarki. Użycie tej komendy sprawia że w rejestrze A pojawia się liczba parametrów jakie są w listingu wpisane po tej komendzie i nic więcej bezpośrednio podane parametry nie zapełniają w rejestrach procka. W ROMie jest procedurka która pozwala pobierać parametry do binarki z listingu Basica i kod musi z niej korzystać by coś robić z kolejnymi parametrami.

Zgaduję że w tym przypadku drugi parametr to adres pod jakim powinny być jakieś dane z którymi coś robi kod spod &4000, np muzyczka którą odtwarza, albo adres pod którym ma umieścić skompresowany obrazek który tworzy ten kod, lub coś podobnego. ;)
- Jeśli masz w domu światło i wodę, tzn. że masz światłowód. ;)

Abrimaal

  • *****
  • Wiadomości: 965
  • Miejsce pobytu:
    Lemmingrad
  • Zamulator
    • Games for ULA plus
Odp: Amstrad Basic
« Odpowiedź #17 dnia: 2015.11.18, 18:14:20 »
You don't have to google that for me. Bez powodu bym nie pytał, CPC Wiki podaje jedynie taki przykład użycia CALL
CALL 0 :REM resets the computer completelyInteresuje mnie, jak ten konkretny przypadek CALL adres,parametr wywołać z assemblera.
AY Music, ULA plus.

matofesi

  • *****
  • Wiadomości: 2048
  • Miejsce pobytu:
    Toruń/Poland
Odp: Amstrad Basic
« Odpowiedź #18 dnia: 2015.11.18, 21:14:38 »
Ale czytałeś trzeci wynik tego wyszukiwania? http://www.cpcwiki.eu/index.php/Technical_information_about_Locomotive_BASIC

Tam jest wyraźnie napisane, że kolejne parametry są adresowane przez IX - ostatni parametr to IX+2/IX+3 a wcześniejsze to kolejne przesunięcia do IX - przedostatni +4/+5 itd. Może to trochę nieintuicyjne, ale opis jest moim zdaniem jasny.

Jeśli procedura oczekuje jednego parametru to w A należy przekazać 1 a parametr zapisać pod adresem  IX+2 i IX+3.

ZbyniuR

  • *****
  • Wiadomości: 3333
  • Miejsce pobytu:
    Carlisle w UK
  • CPC AGA PSX
Odp: Amstrad Basic
« Odpowiedź #19 dnia: 2015.11.18, 21:24:02 »
Assembler Z80 też ma polecenie CALL czyli szesnastkowo &CD + 2 bajty z adresem. Trudniej będzie przekazać tam ten parametr, bo jeśli ta procedura korzysta z tej o której wspomniałem w poprzednim wpisie to szuka tego parametru w listingu Basica. Trzeba by ją przeanalizować by zobaczyć co z tym parametrem robi i od razu wpisać w tym miejscu LD w wersji wciskającej to &5000 pod właściwy rejestr, a resztę bajtów z fragmentem kodu pobierającym ten parametr wyzerować. Zakładam że odwołuje się do ROMu przez tablicę skoków więc odwołuje się do adresu między &BB00 a &BD80. Po tym można by namierzyć gdzie jest ten fragment. Albo z okazji że mamy tylko 3 możliwości gdzie wcisnąć tą 16-bitową liczbę (HL,BC,DE), to wypróbować każdą i może któraś zadziała. Tzn wpierw wysłać ten parametr do pary rejestrów a potem wywołać tego CALL. Jeśli masz szczęście to pobranie tego parametru jest na samym początku tego kodu czyli od &4000 i to tam trzeba tego LD wstawić. A właściwa procedura która rusza już po przekazaniu tego parametru zaczyna się parę/naście bajtów dalej.

Sorry za takie amatorskie tłumaczenie, nie jestem specem, ale sam przed laty tak kombinowałem na chłopski rozum by zmodyfikować parę bajtów w gotowych binarkach. ;)
- Jeśli masz w domu światło i wodę, tzn. że masz światłowód. ;)

matofesi

  • *****
  • Wiadomości: 2048
  • Miejsce pobytu:
    Toruń/Poland
Odp: Amstrad Basic
« Odpowiedź #20 dnia: 2015.11.18, 22:42:22 »
No ręce mi opadają... W jakim listingu BASICa? Oczywiście, że tak też się da, ale po co skoro "system" do kodu maszynowego przekazuje podane po CALL parametry a wskaźnikiem do nich jest IX?

Nie wiem czy i jak dokładnie to działa w praktyce, bo Amstrada dotykałem ostatnio prawie 30 lat temu a to, co robiłem w asmie nie wymagało przekazywania parametrów, ale cytowany artykuł wygląda moim zdaniem całkiem sensownie i nie widzę powodu, żeby ten mechanizm nie miał działać tak jak jest opisany.

RafalM

  • *****
  • Wiadomości: 1133
  • Miejsce pobytu:
    Sulejówek
Odp: Amstrad Basic
« Odpowiedź #21 dnia: 2015.11.18, 23:04:02 »
Cytuj
Ale czytałeś trzeci wynik tego wyszukiwania? http://www.cpcwiki.eu/index.php/Technical_information_about_Locomotive_BASIC

A ty sam to czytałeś Mat? Czy tylko pochwaliłeś się znajomością obsługi Google'a?

Bo ja przed chwilą próbowałem to czytać i nic z tego nie rozumiem:

Both RSX and CALL commands works (are!) similar from BASIC command line and invokes a machine code - the only difference is: with the help of a RSX command you don't need to know the exact access address. You can pass up to 32 parameters with a CALL or RSX command. Possible parameters could integer, floating points and strings. Just store the parameter into a variable: Passing for integer:

CALL &4000,32,34,&5E,&x10101010
|RSX-command,32,34,&5E,&x10101010


No zajebiście, mogą być 32 parametry i czym jest każdy z nich?

Abrimaal

  • *****
  • Wiadomości: 965
  • Miejsce pobytu:
    Lemmingrad
  • Zamulator
    • Games for ULA plus
Odp: Amstrad Basic
« Odpowiedź #22 dnia: 2015.11.18, 23:31:19 »
Wydaje się, że parametry mogą być dowolnymi zmiennymi dla elastycznej procedury, która wielokrotnie odczytuje dane z tej tabeli adresowanej przez IX. Tylko, czy wartość samego IX (lokalizacja tabeli) w momencie przejścia z Basic do procedury jest zawsze stała, czy przypadkowa, czy definiowalna z poziomu Basic, tego już chyba nikt nie wie.
Najlepiej taką procedurę zacząć od PUSH IX, aby nie zgubić adresu bazowego. Gorzej jeśli to gotowy kod i bez instrukcji na papierze czy głębokiej disasm nie wiemy, jakich parametrów oczekuje.
AY Music, ULA plus.

Dr Piotr

  • ***
  • Wiadomości: 196
Odp: Amstrad Basic
« Odpowiedź #23 dnia: 2015.11.19, 04:15:33 »
Co dokładnie robi instrukcja CALL &4000,&5000 ?

Czy to jest wywołanie procedury pod &4000 z wartością &5000 w rejestrze (którym?)

Jest to wywolanie procedury pod &4000 z parametrem &5000, wskazywanym przez rejestr IX. Rejestr A zawiera liczbe parametrow.

matofesi

  • *****
  • Wiadomości: 2048
  • Miejsce pobytu:
    Toruń/Poland
Odp: Amstrad Basic
« Odpowiedź #24 dnia: 2015.11.19, 07:55:58 »
No zajebiście, mogą być 32 parametry i czym jest każdy z nich?

Ależ w opisie - nie wprost - jest napisane. Parametry są "dowolne" co oznacza, że są zależne od tego, czego spodziewa się procedura. To jest przecież wywołanie kodu maszynowego - to autor tego kodu decyduje jakie parametry jego procedura ma dostać i stosownie do potrzeb traktuje to, co dostaje z zewnątrz. A jak użytkownik takiego kodu poda niewłaściwe parametry to już jego problem.

@Abrimaal Jak rozumiem IX w BASICU CPC adresuje jakiś wewnętrzny "stos" i prawie na pewno wartość jest dynamiczna. Jeśli więc chcesz taką procedurę wywołać "z zewnątrz" z innej procedury w kodzie maszynowym (albo np. z emulatora w odtwarzaczu plików AY) to prawdopodobnie wystarczy jak ustawisz IX tak, żeby wskazywał na odpowiednie parametry zgodnie z opisem, potem A na 1 i po prostu wywołasz procedurę.

RafalM

  • *****
  • Wiadomości: 1133
  • Miejsce pobytu:
    Sulejówek
Odp: Amstrad Basic
« Odpowiedź #25 dnia: 2015.11.19, 11:03:52 »
Cytuj
Jest to wywolanie procedury pod &4000 z parametrem &5000, wskazywanym przez rejestr IX. Rejestr A zawiera liczbe parametrow.

A co to znaczy 5000 wskazywane przez IX? Że wartość z dwóch komórek (IX+0)+ 256*(IX+1)=5000?

Czyli czy dobrze rozumiem że takie polecenie CALL z Basica gdzieś tam do pamięci wstawia sobie te parametry a potem tak ustawia IX by wskazywał na początek tej tablicy parametrów?

matofesi

  • *****
  • Wiadomości: 2048
  • Miejsce pobytu:
    Toruń/Poland
Odp: Amstrad Basic
« Odpowiedź #26 dnia: 2015.11.19, 11:46:13 »
Cytuj
Jest to wywolanie procedury pod &4000 z parametrem &5000, wskazywanym przez rejestr IX. Rejestr A zawiera liczbe parametrow.

A co to znaczy 5000 wskazywane przez IX? Że wartość z dwóch komórek (IX+0)+ 256*(IX+1)=5000?

Moim zdaniem tak, tylko nie do końca...
Cytuj
A register holds the number of parameters. IX points to each parameter. IX+0/IX+1 is the last parameter. Each parameter is a 16-bit value.

...

Hint: the first two bytes at the end of stack shows the internal return address from BASIC interpreter where it was executed.

Dlatego (IX+2)+ 256*(IX+3)=5000

Cytuj
Czyli czy dobrze rozumiem że takie polecenie CALL z Basica gdzieś tam do pamięci wstawia sobie te parametry a potem tak ustawia IX by wskazywał na początek tej tablicy parametrów?

Mam wrażenie, że raczej jest tak, że albo wewnętrznie BASIC używa IX do adresowania dna stosu albo ustawia w ten sposób IX na potrzeby BASICowego CALL,  a parametry są po prostu zrzucane na stos.

RafalM

  • *****
  • Wiadomości: 1133
  • Miejsce pobytu:
    Sulejówek
Odp: Amstrad Basic
« Odpowiedź #27 dnia: 2015.11.19, 12:06:50 »
To może ja bym miał pytanie do Zbynia - jaka jest najprostsza, oficjalna,  podstawowa książką/instrukcja dla początkujących o  Basicu na Amstradzie?

Coś jak ta nasza czarna, kolorowa instrukcja do Spectruma

http://www.worldofspectrum.org/infoseekid.cgi?id=2000446

albo podręcznik Basica Vickersa:

http://www.worldofspectrum.org/infoseekid.cgi?id=2000438

matofesi

  • *****
  • Wiadomości: 2048
  • Miejsce pobytu:
    Toruń/Poland
Odp: Amstrad Basic
« Odpowiedź #28 dnia: 2015.11.19, 12:36:23 »
I sprawdziłem... Znalazłem disassemblację ROMu CPC - http://www.cpcwiki.eu/index.php/ROM-Listing_CPC_464/664/6128

Niestety jest po niemiecku i w bitmapach więc słabo się szuka, ale da się znaleźć istotne informacje.
Obsługa CALL siedzi (w 464, bo to przeglądałem, ale reszta powinna być chyba zbliżona) pod adresem F1BA. Najpierw pobiera adres wywołania (czyli pierwszy parametr) i zapisuje go pod adres AE72. Potem zapamiętuje stos do zmiennej a następnie w pętli pobiera kolejne parametry - za każdym razem używa procedury CE91, która parsuje wyrażenia i zwraca wartość w DE (zachowując pozostałe rejestry). Tak pobrana wartość zrzucana jest na stos a na zakończenie pętli do A zapisywana jest faktyczna liczba odczytanych parametrów i wykonywany jest kod:
ld ix,0
add ix,sp
rst 18
dw ae72

Restart 18 to procedura "dalekiego wywołania" z ewentualnym przełączaniem banków itp. Procedura nie rusza IX tylko pobiera parametr podany za RST do DE przestawiając równocześnie na stosie adres powrotu o dwa bajty. Pobrany parametr traktowany jest jako wektor skoku - spod tego adresu pobierany jest jeszcze raz do DE adres - tym razem właściwy adres wywoływanej przez BASICowy CALL procedury i następuje skok do niego poprzez kombinację PUSH DE/RET.

Oczywiście w samej procedurze dzieje się więcej, ale zasadniczo nie ma to znaczenia dla meritum sprawy. Istotne jest to, że na wejściu do wywoływanej procedury w IX znajduje się kopia SP tuż sprzed RST czyli IX wskazuje na ostatni parametr więc jednak jeśli wywołujemy procedurę z jednym parametrem to znajduje się on pod (IX+0)+ 256*(IX+1).

Jakby ktoś chciał sprawdzać głębiej, to obsługa CALL w PDFie znajduje się na stronie 554, RST 18 na stronie 217 a sama procedura obsługi skoku na stronie 233.

RafalM

  • *****
  • Wiadomości: 1133
  • Miejsce pobytu:
    Sulejówek
Odp: Amstrad Basic
« Odpowiedź #29 dnia: 2015.11.19, 13:08:50 »
Dzięki za research.

To jest chyba troszkę bardziej skomplikowane, bo tam jako parametry mogą być nie tylko dwubajtowe liczby ale i jednobajtowe a także ułamkowe i stringi. Wówczas pewnie zajmują odpowiednio różną ilość bajtów pamięci i musimy to uwzględnić w naszej procedurze.

Na koniec mam uwagę natury ogólnej ;) Zawsze miałem wrażenie że mieszanie Basica i assemblera jest dość zagmatwane i jest tam wiele miejsc w których coś może pójść źle . Chyba wolę czyste sytuacje - albo 100% w Basicu, albo 100% w assemblerze :)