atarionline.pl Kod maszynowy w BASIC-u (DATA, strona 6), zmiana lokalizacji - Forum Atarum

Jeśli chcesz wziąć udział w dyskusjach na forum - zaloguj się. Jeżeli nie masz loginu - poproś o członkostwo.

  • :
  • :

Vanilla 1.1.4 jest produktem Lussumo. Więcej informacji: Dokumentacja, Forum.

    • 1: CommentAuthorbartgo
    • CommentTime3 Jan 2024 zmieniony
     
    Jestem zielony w asemblerze. Mam sobie kod z Bajtka (LINIJKA) - ładuje kod na stronę szóstą, sprawdza sumę kontrolną i uruchamia.

    Chcę wziąć ten kod maszynowy i wsadzić w "słowo" Forth-a. Niestety, nie mogę użyć strony szóstej (są tam bufory do obsługi dyskietki).

    Jakie kroki należałoby wykonać, żeby sprawdzić czy kod można umieścić "gdzieś indziej" i ewentualnie zmodyfikować?

    Chyba:
    - zrobić deasemblację robaczków do mnemoników i danych (jakiś tool w basicu albo ręcznie na kartce)
    - namierzyć które mnemoniki to adresowanie zależne od umiejscowienia w pamięci
    - "zmienić"
    - przemalować kod z powrotem na maszynowy

    Czy dobrze kombinuję? Inne sugestie?
    • 2: CommentAuthorZenon
    • CommentTime3 Jan 2024
     
    Jeżeli kod jest relokowalny to zmienić linię 10 na inne adresy (wolne), zachowując miedzy nimi tą samą różnicę.
    Zmienić w lini 30 adres początku kodu, stąd Basic uruchomi kod
    A jeżeli nie jest relokowalny to, odcyfrować co autor miał namyśli i pozmieniać adresy. Jednocześnie zmienić w linii 20 wartość sumy kontrolnej
    • 3:
       
      CommentAuthorjhusak
    • CommentTime3 Jan 2024 zmieniony
     
    Najprościej to przenieść na inny adres, np. większy o 42, zrobić usr(1536+42) i zobaczyć, co z tego wyjdzie. Jak tak samo - znaczy, że kod relokowalny.
    Jednak wydaje mi się, że widzę tam charakterystyczne 33,6, potem 41,6, potem znowu 33,6, co oznaczało by dane bezwzględne.
    Poza tym, jak to uruchomisz w emulatorze, to dezasemblacja, mimo, że jesteś zielony, to będzie dość przejrzysta. Bo asembler to:

    lda #$60 ; load akumulator
    sta 712 ; store akumulator

    i już masz poke (712,$60)

    6502 ma 3 rejestry: a (akumulator) ,x,y, - indeksowe, reszta to prościzna. W jeden wieczór załapiesz.

    Najpierw robisz proste programiki, typu przepisz generator znaków:
    ldy #0
    loop
    lda romgenerator,y
    sta ramgenerator,y
    lda romgenerator+256,y
    sta ramgenerator+256,y
    lda romgenerator+512,y
    sta ramgenerator+512,y
    lda romgenerator+768,y
    sta ramgenerator+768,y
    iny
    bne loop
    rts

    A potem bardziej skomplikowane :)
    • 4: CommentAuthorlzd
    • CommentTime3 Jan 2024 zmieniony
     

    jhusak:

    Jednak wydaje mi się, że widzę tam charakterystyczne 33,6, potem 41,6, potem znowu 33,6, co oznaczało by dane bezwzględne.

    Jest też kod, który sam siebie modyfikuje, np: 141,33,6, czyli STA $0621 nadpisuje pierwsze wystąpienie 38 w linii 50.

    Biorąc pod uwagę niewielki rozmiar programu, przepisanie go pod inny adres jest chyba najlepszym rozwiązaniem. Przy okazji można spróbować przerobić go na niezależny od pozycji w pamięci.
    • 5: CommentAuthorbartgo
    • CommentTime3 Jan 2024
     
    Dzięki!

    Czyli przykładowo, jeśli STA $0621 pakuje wartość z A do $21 na stronę 6, mógłbym to przerobić na adresowanie idące od początku miejsca na kod = offset (?) $21 bajtów. Całość raczej nie będzie się zaczynała od początku strony, więc ostatecznie nie będzie tam szóstek, będzie inny kod operacji itp.

    Więc następny krok to muszę odpalić kod pod bejzykiem i deasemblować stronę szóstą, szukając różnych trybów adresowania - deasemblerem który NIE ładuje się na stronę szóstą albo wbudowanym w emulator :)
    • 6: CommentAuthormarok
    • CommentTime3 Jan 2024
     
    Zmiana postaci kodu na właściwą (cyfr w liniach DATA) pod inny już adres umieszczenia nie musi oznaczać konieczności deasemblacji (choć działając pod emulatorem powinno się z tej sposobności skorzystać - dla pewności czy w dobrym miejscu za każdym razem podmieniamy cyfrę 6 na inną, obraną - i na tym też polega cały "modus operandi" tej transformacji kodu pod inny adres).

    Żeby to zadziałało, po tak prosto przeprowadzonych zmianach, trzeba tylko dopilnować by nowy adres lokalizacji kodu (po przeniesieniu) rozpoczynał się ponownie, jak dla adresu 1536, od początku strony pamięci (tzw. wyrównanie do granicy strony, czyli adres podzielny przez 256).

    W teorii może się zdarzyć, że nie każda wartość cyfrowa 6 powinna być zmieniona, bo może ona odnosić się do młodszej połówki adresu bezpośredniego (a naszym celem jest wyłącznie podmienić starszą połówkę adresu) lub być argumentem dla trybu natychmiastowego adresowania rozkazu, akurat bez związku z adresem lokalizacji programu.

    Taka zmiana na szybko ma szansę okazać się na tak krótkim kodzie ("przypadkowo") całkowicie prawidłową.


    > "Całość raczej nie będzie się zaczynała od początku strony, więc ostatecznie nie będzie tam szóstek"

    nie tylko że nie będzie tam szóstek, ale wszystkie wartości poprzedzające szóstkę (bo taki jest szyk argumentów adresu dla trybu adresowania bezpośredniego, że najpierw idzie młodsza połówka adresu) będą powiększone o jakiś parametr p - stałego przesunięcia od początku strony
    • 7:
       
      CommentAuthorjhusak
    • CommentTime3 Jan 2024 zmieniony
     
    @bartgo - możesz użyć dis6502 czy to w wersji pod linuksa, czy też interaktywne narzędzie ebiguy:
    ->link<- dla windows.

    Jak zdezasemblujesz, to powinieneś wpaść na pomysł, jak zrobić zmienne na stronie zerowej :)

    Śmieszne (i niezłe), wrzuciłem ten obrazek z kodem do ->link<-
    i w liczbach się w ogóle nie pomylił, tylko zamiast zmiennej I było 1. No i U zamiast O w komentarzu.
    • 8:
       
      CommentAuthorjhusak
    • CommentTime3 Jan 2024 zmieniony
     
    wyszło:
    0600: 68        PLA
    0601: A9 16 LDA #$16
    0603: 8D 28 02 STA $0228 ;CDTMA2
    0606: A9 06 LDA #$06
    0608: 8D 29 02 STA $0229 ;CDTMA2+1
    060B: A9 08 LDA #$08
    060D: 8D 1A 02 STA $021A ;CDTMV2
    0610: A9 40 LDA #$40
    0612: 8D 0E D4 STA $D40E ;NMIEN
    0615: 60 RTS
    0616: AD DC 02 LDA $02DC ;HELPFG
    0619: F0 2B BEQ $0646
    061B: EE 21 06 INC $0621
    061E: A9 20 LDA #$20
    0620: 8D 26 9C STA $9C26
    0623: EE 29 06 INC $0629
    0626: A9 02 LDA #$02
    0628: 8D 25 9C STA $9C25
    062B: AD 21 06 LDA $0621
    062E: C9 3C CMP #$3C
    0630: D0 0F BNE $0641
    0632: A9 26 LDA #$26
    0634: 8D 21 06 STA $0621
    0637: A9 02 LDA #$02
    0639: 8D 3C 9C STA $9C3C
    063C: A9 25 LDA #$25
    063E: 8D 29 06 STA $0629
    0641: A9 00 LDA #$00
    0643: 8D DC 02 STA $02DC ;HELPFG
    0646: A9 08 LDA #$08
    0648: 8D 1A 02 STA $021A ;CDTMV2
    064B: 60 RTS
    • 9: CommentAuthorbartgo
    • CommentTime3 Jan 2024 zmieniony
     
    Super pomoc, nie spodziewałem się takiego odzewu :)

    Zajrzałem do Ruszczyca (tym razem nie do Fortha) i chyba łapię:
    - PLA - chyba nie potrzebne, zresztą zaraz akumulator jest nadpisany
    - LDA #$... - nie zmieniam
    - LDA/STA $ - jeśli NIE JEST to strona 6 to są to konkretne operacje których adres musi zostać jak jest (przerwania, ANTIC, obsługa klawiszy itp); jeśli strona 6 to zmieniam żeby wskazywało odpowiednie komórki pamięci (lub jakieś zmienne Forth, zobaczy się)
    - z rozgałęzieniami (BEQ, BNE) pewno poradzę sobie natywnymi instrukcjami asemblera Forth (IF, itp).
    - itd, usiądę na spokojnie to rozbroję
    - niejasne na razie jest tylko dla mnie RTS pod 0615 - nie widzę jak wskoczyć do dalszej części kodu ale ogarnę, to już kwestia prześledzenia


    Dzięki.

    I Zientara się przydaje teraz - PPSO, super!!
    • 10:
       
      CommentAuthormaly_swd
    • CommentTime3 Jan 2024 zmieniony
     
    Pla na początku jest potrzebne jak uruchamiasz kod z basica przez usr. Coś jest potem chyba ze stosu ściągane. Ale mogę się mylić to było 30 lat temu..
    • 11:
       
      CommentAuthorjhusak
    • CommentTime3 Jan 2024 zmieniony
     
    Usr() na dzieńdobry wrzuca na stos ile argumentów jest podanych (o ile dobrze pamiętam). Stąd puste pla. Następny fragment od 616 to jest przerwanie, bo do 228 i 229 wpisany jest ten adres na. początku.
    228,229 CDTMA2
    System timer two jump address. Not used by the OS, available to
    user to enter the address of his or her own routine to JMP to when
    the timer two (538, 539; $21A, $21B) count reaches zero.
    Initialized to zero; the address must be user specified. NMI



    Więc ta procedura od 616 wykonuje się na przerwaniach, zapewne co 8 ramek :)

    218,219 CDTMV1
    System timer one value. Counts backwards from 255. This SIO
    timer is decremented every stage one VBLANK. When it reaches
    zero, it sets a flag to jump (JSR) through the address stored in
    locations 550, 551 ($226, $227). Only the realtime clock
    (locations 18-20; $12-14), timer one, and the attract mode
    register (77; $4D) are updated when the VBLANK routine is cut
    short because time-critical code (location 66; $42 set to non-zero
    for critical code) is executed by the OS. Since the OS uses timer
    one for its I/O routines and for timing serial bus operations
    (setting it to different values for timeout routines), you should use
    another timer to avoid conflicts or interference with the operation
    of the system.
    • 12: CommentAuthorbartgo
    • CommentTime3 Jan 2024
     
    No tak, i już widzę skąd to RTS w środku kodu. Super!

    PLA usuwa liczbę parametrów ze stosu (pewno jest ich zero). Jeśli Forth nie używa tego, do wywalenia.

    Ostatnio tak się podjarałem przy kupnie stacji 1050. Czyli, miesiąc temu :)