assembler call i ret brak adresu zwrotnego

0

Witam
piszę prosty program w asm, i napotkałem na problem z call i ret

platforma - brak, piszę coś na zasadzie bootloadera także nie istotne,
kompilator fasm
ładuje sobie pierwszy kod pod np 0500h:0000h a następny pod 7c00h:0000h
i teraz w kodzie z pierwszego chciałbym "wyskoczyć" do 7c00h aby wykonać kod i powrócić.. więc zrobiłem coś takiego:

;kod z 0500h:0000h

mov al,1
call [cos] ;;;skacze do 7c00h:0000 < tutaj robi to co chcę i dalej wykonują się instrukcje spod tego adresu`


cos dd 7c00h:0000h

;/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

;kod z 7c00h:0000h

or al,al
jz pomin
;;;instrukcje do wykonania

ret <- i tutaj marzyło by mi się aby powrócił do 0500h:miejsce gdzie skończył....co się niestety nie dzieje...




pomin:
pop ax ;; zeby oczyscic stos
;;takie tam inne funkcje

pewnie to jakaś głupota bo już zbyt długo nad tym siedzę.... bardzo proszę o pomoc

0

A nie wrzuciłeś na stos przypadkiem czegoś jeszcze w tej funkcji/ nie zdjałeś za dużo? Bo rozumiesz że ret to nie magia, tylko po prostu ściąga ze stosu adres powrotu i tam skacze ;]

0

właśnie się zastanawiam... ale nie ... umieścił bym tutaj cały kod ale jest go za dużo i nikomu nie chciało by się tego analizować...
wiem jak działa call i ret, ale nie jestem pewien czy to co umieszcza na stosie to adres segmentu i przesunięcia? czy tylko przesunięcia?

1
call [cos]
cos dd 0x7c00h:0000h

Po primo (choć nie jest to przyczyną problemu), to nie działa tak jak myślisz. Bo zakładam że myślisz że gdyby cos było zadeklarowane jako np.
1234h:4321h to ten call skoczyłby pod 0x16661 ( (0x1234*16)+0x4321). Otóż nie, bo nie ma takiego kodowania dla instrukcji 8086, i finalnie wykonuje się to jako call 1234h i druga część jest pomijana. Jeśli to działa, to jest to zasługą asemblera gdyż sobie to po prostu tam podstawia.

A apropos głównego problemu to:

  • Możesz gdzieś po drodze naruszyc/nadpisać stos.
  • Możesz gdzieś po drodze zmienić segment SS.

Proponuje przeklikać to pod debuggerem a wszystko będzie jasne. I przyjrzyj się temu callowi pod disassemblerem.

// Ad pytania co call umieszcza, to umieszcza on adres 'przesunięcia', i przy ret adres absolutny obliczany jest względem bieżącego stanu rejestru CS

0

konkretnie! bardzo dziękuje za odpowiedź, niestety nie rozwiązało to mojego problemu ponieważ stos pozostaje nienaruszony...
sprawdziłem na czystym kodzie...
skacząc tak daleko.. cs zmienia się
Więc próbowałem je umieścić na stosie i potem przywrócić jednak nic to nie dało...

muszę to ogarnąć bo w przeciwnym razie pozostaje mi warunkowanie kodu czyli skok bezpośredni z warunkiem i po spełnieniu kolejny skok do etykiety a to trochę się mija z celem

1

Dobra, chyba wiem o co chodzi.
Nie jest możliwe żeby pobrać z pamięci i segment, i offset, bo nie ma takiej instrukcji która by to robiła.
Warianty są dwa.

  • Asembler domyśla się co stoi za labelem cos i wstawia zupełnie inny opkod
  • Asembler ignoruje offset (xxxx:tą częśc) i skacze pod xxxx
    Jeśli mówisz że zmienia Ci się CS to prawdopodobnie jest to wariant 1.
    Żeby się upewnić sprawdź to pod disassemblerem. W snippecie niżej widać różnicę.
    
; być może asembler zamiast tego na dole wstawia taką instrukcję bo się domyśla.
3:   9a 00 00 1a fa          call   0x0:0xfa1a 
8:   ff 16 fe fa                   call   WORD PTR ds:0xfafe 

0x9a modyfikuje CS i skacze pod (cs16)+0xfa1a.
0xff Pobiera z (ds
16)+0xfafe jakiś adres, i pod niego skacze.

Więc, jeśli masz tam opkod 0x9a to modyfikowany jest CS i mimo tego że stos nie jest zmieniany adres powrotu wskazuje w zupełnie inne miejsce bo CS jest inny.
Nie za bardzo da radę go zapisać i potem przywrócić. Musiałbyś na nowo przeliczyć offset żeby nie skoczył w randomowe miejsce. Proponuje Ci, abyś nie zmieniał wartości CS jeśli możesz.

0

coś mi się nie klei teraz... tak przeglądam ten kod i opcode
i gdy dam :

call 1000h:0001h to w op code pojawi się faktycznie 9a

ale jeśli dam np call etykieta to już cs pozostaje nie naruszone... i podobnie jest z call [etykieta]
już dziś jest późno i mój mózg tego nie może przerobić :) ale jutro się nad tym trochę pogłówkuje i napisze co udało się ustalić.

0

No i jest! jest przełom !!!! cs może być modyfikowane...to nie przeszkadza.. zrobiłem kilka skoków i ret wrócił... ale rozwiązaniem jest retf zamiast ret :) można zamknąć temat!!!! Proxima Bardzo dziękuje za pomoc, gdyby nie ty nie dałbym rady ;) dobranoc

1 użytkowników online, w tym zalogowanych: 0, gości: 1