[ petrovic @ 27.08.2003. 09:59 ] @
Da li je na Intel x86 moguce kodirati apsolutni skok?
Recimo jmp 0x12345678, ali ne instrukcija koja pocinje sa 0xe9. Znam za far jmp, ali on zahteva da se navede i segment (jmp 0x1234:0x12345678), a meni treba apsolutni skok u istom segmentu.
[ Sundance @ 27.08.2003. 12:17 ] @
operand za 0e9h je relativna adresa, a ne apsolutna. a zoke za segment override ne koristis cs/ds?
Code:

        jmp cs:addr

mozes koristiti i nesto tipa
Code:

        mov eax, addr
        jmp eax

        push addr
        retn

ja preferiram ovo drugo kad mi treba skok na apsolutnu adresu (btw, zasto ti ovo treba uopce?). ljepsa verzija preko makroa:
Code:

jumpa macro address, dummy
        errifnb <dummy> "Previse argumenata u makrou jumpa"
        push address
        retn
endm
[ petrovic @ 27.08.2003. 13:55 ] @
Da, na kraju sam izabrao ovo drugo (push addr/retn). Zaboravio sam da spomenem
da mi takodje treba i call, mada moze da prodje
mov eax, addr
call eax
iako mi se ne svidja sto unistava eax. Jel ima mozda nesto bolje?

A sve ovo mi treba jer sam napisao primitivan (ali vrlo efikasan) relocatable
loader i patcher za jednu igru. Reference ka podacima rade odlicno, jer je to
sve apsolutno, ali skokovi i pozivi su bili problem jer su relativni.
Klasican primer je:
- patchovati neku adresu u igri, zameniti sa jmp my_code
- my_code se nalazi u mom kodu, koga ucitava loader i tu vec nastaje problem
kako izracunati relativni offset (a win32 asembleri i kompajleri ne izdaju
fixup record za skokove)
- u my_code se takodje nalaze pozivi raznim funkcijama unutar igre, i na kraju
jmp sledeca_instrukcija_u_igri; to takodje treba povezati
Ali ako koristim ove stosove, onda je sve u redu, jer su reference ka podacima
sredjene pre izvrsenja. Mislio sam da ima neki "legitiman" nacin, neka
instrukcija jmp/call <absulte address>, da ustedim koji bajt i da ne
prepisujem previse koda.
[ Sundance @ 27.08.2003. 14:07 ] @
bez izmjene registara mozes (prvo sto mi pada na pamet):
Code:

calla macro address, dummy
        errifnb <dummy> "Previse argumenata u makrou calla"
        push address
        call (esp).dword ptr 0
        add esp, 4 ; ili pop ecx/edx ili neki dummy registar  koji se mijenja pri pozivu
endm
[ petrovic @ 28.08.2003. 12:01 ] @
Nije losa ideja, samo sto zauzima dosta bajtova. Razmisljao sam o problemu, i
sastavio sam listu svega (ukljucujuci i tvoje ideje) sto bi moglo da dodje u
obzir za call. Hvala na pomoci.

Code:

(1)
mov  eax, addr
call eax
5 + 2 = 7 bajtova (unistava eax)

(2)
push eax
mov  eax, addr
call eax
pop  eax
1 + 5 + 2 + 1 = 9 bajtova

(3)
push addr
call dword [esp]
add  esp, 4
5 + 3 + 3 = 11 bajtova

(4)
push addr
push addr
retn
5 + 5 + 1 = 11 bajtova (+ dodatni fixup 4 bajta)

u pocetku sam koristio ovo:
(5)
nasm makro:
%macro calla 1
[section .data]         ; prebaci se u .data sekciju
%%addr:
    dd %1               ; stavi na %%addr nalazi ciljnu adresu
__SECT__                ; vrati se na sekciju u kojoj si bio
    call dword [%%addr] ; indirektni skok
%endmacro
4 bajta u .data + 6 = 10 bajtova, ali posto nemam nacina da iz makroa proverim
koje su sve adrese vec bile, svaki naredni poziv istoj funkciji nepotrebno
ponovo stavlja istu adresu u .data


Verovatno je najbolje kombinovati opcije (1) i (2) preko makroa:
calla 0x12345678 ; mov eax, 0x12345678/call eax
calla 0x12345678, ecx ; mov ecx, 0x12345678/call ecx
calla 0x12345678, push ; push eax/mov eax, 0x12345678/call eax/pop eax