Wpis użytkownika 6502 w Hydepark
6502Autorytet
1piorunówMamy tu jakiegoś eksperta od assemblera Z80? Chodzi mi o wstawki assemblerowe w sdcc. Funkcja, która ma skoczyć bezwarunkowo pod adres:
>void run(char* address){
>__asm
>pop HL
>jp (HL)
>__endasm;
>}
Kompiluje się prawidłowo, ale nie działa. Ktoś może mi wytłumaczyć dlaczego? Ja to rozumiem w następujący sposób:
-argument przy wywołaniu funkcji jest wrzucany na stos
-instrukcja "pop HL" ściąga argument ze stosu do rejestru HL
-"jp (HL)" skacze bezwarunkowo pod adres przechowywany w rejestrze HL.
program zachowuje się tak, jakby nic się nie wykonało.
Komentarze (12)
@ataxbras @MostlyRenegade @inskpektor
Problem częściowo rozwiązany - zerknąłem w pośredni kod asemblera generowany przez sdcc. Parametr nie jest przekazywany przez stos, tylko przez rejestr hl, więc samo "jp (HL)" załatwia sprawę. Nadal działa to tylko w przypadku przekazania wskaźnika na funkcję, przy 0x0000 się wiesza. Edit: jednak działa, problem jest chyba przy powtórnej inicjalizacji UARTa bez soft resetu :smiley:
@6502 pod debugerem sprawdź co tam się faktycznie dzieje
@inskpektor Nie ma debuggera 😉
Nie jesteście normalni, wracajcie do piwnicy ;)
@6502 Ale co ma się zadziać, skoro zwracasz void? Skoczyło i tyle.
@MostlyRenegade 0x0000 to początek ROMu na mojej płytce i jednocześnie początek programu.
@ataxbras Na dobrą sprawę nie przekazuję nic bezpośrednio do assemblera tylko ściągam ze stosu i właśnie o takim sposobie czytałem. Z global też spróbuję tylko muszę doczytać jak to zdefiniować, bo wydaje mi się że próbowałem z typową zmienna globalna zadeklarowana poza mainem i to wywalało jakiś błąd as linkera.
@6502 W asm pykałem ze 25 lat temu, więc specem już dawno nie jestem (demencja :D). Tym bardziej nie jestem specem od SDCC, choć z C mam podobnie długą historię.
Jednak z tego co udało mi się wyłapać z sieci (bo Twój wpis spowodował, że stałem się sentymentalny i zacząłem grzebać), to wstawki asm w sdcc nie akceptują parametrów innych, niż global. Stąd, powinieneś przepisać zmienną wejściową funkcji do jakiejś zmiennej globalnej.
Ponadto, asm zwraca zawsze (nie ma potrzeby return), ale ty wymuszasz void. Nie wiem, czy to ma jakiś wpływ, ale widziałem deklaracje z __naked, które wyglądały dla mnie bardziej sensownie.
@6502 ale dlaczego skaczesz do 0x0000, a nie tam, gdzie program jest załadowany?
@ataxbras Nie widzę efektów skoku. Wywołuję funkcję z argumentem 0x0000, a program nie zaczyna się wykonywać od początku. Edit: i nie wywala się jak podam jakiś losowy adres.