|
[ mihajilo @ 31.03.2005. 07:29 ] @
| e ovako: zanima me da li neko moze da postavi neke primere iz asemblera sa nizovima i dvostrukom preciznoscu(naravno sa textom zadataka).pored toga da li bi neko mogao malo da mi objasni taj rad sa nizovima(one osnovne stvari)?
unapred hvala |
[ Vojislav Milunovic @ 31.03.2005. 12:27 ] @
Nizovi prosto, a dvostruka preciznost pojma nemam sta je... to moras da das neki priemr da vidim sta je ili ako neko zna sta taj termin predtsavlja na nasem nek pomogne.
Nizovi -> Alociras memoriju koja ce ti sluzii za niz. Bilo preko .data sectiona ili preko VirtualAlloc, to tebi ostavljam da odlucis.
Onda adresu niza prebacis u neki registar i prostim indexisranjem nadjes sta te zanima u nizu:
recimo da ti treba niz pointera :
Code:
call VirtualAlloc, 0, 1000h, MEM_COMMIT, PAGE_READWRITE
mov ebx, eax
;I sad ovako-> ako ti treba 5ti pointer onda uzmes:
mov esi, dword ptr[ebx+5*4]
Isto je sa strukturama
mov esi, dword ptr[ebx+5*velicina_Strukture]
itako dalje i tako dadalje u zavisnosti koji ti clan niza treba...
[ Sundance @ 31.03.2005. 18:11 ] @
Mislim da pod dvostruka preciznost misli na double u C-u, ali nije baš iz konteksta jasno na koji asembler i arhitekturu misli :) Mislim, puno ih je ovdje sa ETF-a gdje još uče 16-bitni real-mode... jeli ti treba primjer kako koristiti 32-bitni FPU u nizu koji sadrži broj dvostruke preciznosti ili šta?
[ _NEShA_ @ 31.03.2005. 18:30 ] @
Verovatno misli na situaciju kada dva 32-bitna broja cine 1 64-bitni broj.
[ mihajilo @ 31.03.2005. 21:00 ] @
da mislim kada dva 32 bitna broja cine jedan 64 bitni(pa se taj jedan broj smesta u dva registra).mene zanimaju neki primeri operacija u toj dvostrukoj preciznosti(u osnovi znam sabiranje i oduzimanje,manje vise bi se snasao sa mnozenjem i deljenjem-u dvostrukoj preciznosti), ali trebao bi mi neki primer koji ce kombinovati rad sa nizovima kod koji se sastoji od 64 bitnih brojeva i nad njima se vrse operacije u dvostrukoj preciznosti(moze se jos i dodati rad sa stekom).bio bih zahvalan ako bi neko imao negde neki takav primer
[ Vojislav Milunovic @ 31.03.2005. 23:13 ] @
Hmmm primer nemam, ali za te svrhe definitnivno treba koristiti FPU koji to omogucava.
Uz poruku sam ti uploadovao jedan tekst o koriscenju FPU instrukcija, iskreno ih nikad ne koristim jer mi ne trebaju tako slozene matematicke operacije :)
[ Sundance @ 01.04.2005. 06:20 ] @
Pa obično koristiš edx:eax kao jedan 64-bitni broj i gledaš one krajnje slučajeve za preljeve/podljeve i kako odrediti algoritam za prijenos zastavica.
A što se tiče nizova, najbolje bi bilo da ih u memoriji definiraš kao strukturu od 2 DWORD-a, i onda zasebno nad njima vršiš operacije kako ih čitaš. Mislim da je pod win32 struktura LARGE_INTEGER nešto sl.
[ Sundance @ 01.04.2005. 06:49 ] @
Evo što je MS VC++ kompajler generirao pod debug buildom za niz tipa __int64, jednostavna dodjela u petlji:
Code:
__int64 x[100];
for ( int i = 0; i < 100; i++ )
x[i] = i;
Dobiješ ovo:
Code:
; 12 : __int64 x[100];
; 13 :
; 14 : for ( int i = 0; i < 100; i++ )
mov DWORD PTR _i$31668[ebp], 0
jmp SHORT $LN3@main
$LN2@main:
mov eax, DWORD PTR _i$31668[ebp]
add eax, 1
mov DWORD PTR _i$31668[ebp], eax
$LN3@main:
cmp DWORD PTR _i$31668[ebp], 100 ; 00000064H
jge SHORT $LN1@main
; 15 : x[i] = i;
mov eax, DWORD PTR _i$31668[ebp]
cdq
mov ecx, DWORD PTR _i$31668[ebp]
mov DWORD PTR _x$[ebp+ecx*8], eax
mov DWORD PTR _x$[ebp+ecx*8+4], edx
jmp SHORT $LN2@main
Obrati pažnju na korištenje cdq te indeksiranje sa ecx*8.
Nadalje, za množenje u obliku:
Code:
__int64 x[100];
__int64 y[100];
for ( int i = 0; i < 100; i++ )
x[i] = y[i] = i;
for ( int i = 0; i < 100; i++ ) {
x[i] = x[i] * y[i];
je generirao (samo za ovu drugu for petlju):
Code:
; 19 :
; 20 : for ( int i = 0; i < 100; i++ ) {
mov DWORD PTR _i$31673[ebp], 0
jmp SHORT $LN3@main
$LN2@main:
mov eax, DWORD PTR _i$31673[ebp]
add eax, 1
mov DWORD PTR _i$31673[ebp], eax
$LN3@main:
cmp DWORD PTR _i$31673[ebp], 100 ; 00000064H
jge SHORT $LN1@main
; 21 : x[i] = x[i] * y[i];
mov eax, DWORD PTR _i$31673[ebp]
mov ecx, DWORD PTR _i$31673[ebp]
mov edx, DWORD PTR _y$[ebp+ecx*8+4]
push edx
mov ecx, DWORD PTR _y$[ebp+ecx*8]
push ecx
mov edx, DWORD PTR _x$[ebp+eax*8+4]
push edx
mov eax, DWORD PTR _x$[ebp+eax*8]
push eax
call __allmul
mov ecx, DWORD PTR _i$31673[ebp]
mov DWORD PTR _x$[ebp+ecx*8], eax
mov DWORD PTR _x$[ebp+ecx*8+4], edx
jmp SHORT $LN2@main
Očito se sva zabava odvija u fji __allmull(LARGE_INTEGER x, LARGE_INTEGER y), pa sa je disasmao sa IDA-om i nakon sređivanja dobio ovo:
Code:
__allmull proc near ; CODE XREF: j___allmullj
x = _LARGE_INTEGER::$837407842DC9087486FDFA5FEB63B74E ptr 4
y = _LARGE_INTEGER::$837407842DC9087486FDFA5FEB63B74E ptr 0Ch
mov eax, [esp+x.HighPart]
mov ecx, [esp+y.HighPart]
or ecx, eax
mov ecx, [esp+y.LowPart]
jnz short __ima_vise_od_32_bita
mov eax, [esp+x.LowPart]
mul ecx
retn 10h
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
__ima_vise_od_32_bita: ; CODE XREF: __allmull+Ej
push ebx
mul ecx
mov ebx, eax
mov eax, [esp+4+x.LowPart]
mul [esp+4+y.HighPart]
add ebx, eax
mov eax, [esp+4+x.LowPart]
mul ecx
add edx, ebx
pop ebx
retn 10h
__allmull endp
Na sličan način možeš vidjeti i za ostale operacije kakav kod kompajler generira pa ti to može poslužiti kao uzor za pisanje asm koda.
[ Zevs85 @ 02.04.2005. 16:46 ] @
Moze li neko to da mi objasni kako ta realizacija izgleda u steku, posto ja koliko razumem na stek se odvajaju dve 32-obitne lokacije da bi se iz niza unela jedna vrednost... Jesam u pravu?!?! Ili se iz niza uzimaju dva elementa i upisuju na stek tako sto jedan smatramo visom pozicijom (da ima visu adresu), a drugi nizu....?!?!
[ Sundance @ 02.04.2005. 16:57 ] @
Točno tako! :)
__int64 tip kompajler "emulira" na arhitekturi koja ima 32-bitne GP registre koristeći 2 DWORD-a. LARGE_INTEGER struktura sadrži i gornji (HighPart) i donji (LowPart) dio, svakome od njih se zasebno pristupa te se zasebno push-aju na stog. Recimo u slučaju FP bi mogao koristiti fild/fistp qword ptr [x] tj. direktno, ali jebiga, tražio si primjer emulacije :)
[ Bensedin @ 07.04.2005. 12:22 ] @
evo jedan zadatak,ali nemam resenje.pomoc ne bi skodila ako neko zna da resi.hvala.
Napisati potprogram za nalazenje maximuma niza oznacenih celih brojeva u jednostrukoj preciznosti,kao i broja maksimalnih elemenata.Prenos argumenata odraditi preko registara,i to:
eax-adresa niza(ulaz)
ebx-broj clanova niza (ulaz)
ecx-maksimum(izlaz)
edx-broj maksimalnih elemenata(izlaz)
[ Vojislav Milunovic @ 07.04.2005. 20:10 ] @
otprilike ovako, pisem iz tintare:
Code:
mov ecx, ebx
xor edx, edx
__loop:
cmp dword ptr[eax+ecx*4], edx
jb __skip0:
mov edx, dword ptr[eax+ecx*4]
__skip0:
loop __loop
;i sad koliko ih ima
mov ecx, ebx
xor ebx, ebx
__loop1:
cmp dword ptr[eax+ecx*4], edx
jne __skip1:
inc ebx
__skip1:
loop __loop1
mov ecx, edx
mov edx, ebx
[ Bensedin @ 08.04.2005. 11:35 ] @
e super ,hvala na pomoci.
[ mihajilo @ 08.04.2005. 12:40 ] @
Code:
#define clanova $6
.section .data
niz:
.long 5
.long 6
.long 11
.long 13
.long 12
.long 2
.long 7
.long 8
.long 64
.long 32
.long 64
.long 32
maksimumg: .long 0
maksimumd: .long 0
brojmax: .long 1
.section .text
pp1:
xorl %ebx,%ebx #ponistimo sadrzaj registra ebx(inicijalizujemo ga na nulu)
movl $1,%edx #prosledimo 1 u edx,pretpostavka je da je bar jedan element najveci
movl $niz,%eax #prosledimo adresu niza u eax
movl clanova,%ecx
addl %ecx,%ecx
movl %ecx,%edi
kreni: movl (%eax,%ebx,4),%ecx #prosledimo prvih 32 bita prvog clana niza u registar ecx
cmpl %edi,%ebx
je krajpp1
cmpl %ecx,maksimumg
jl vece
je isto
addl $2,%ebx #uvecavamo brojac za 2 jer poredimo samo 32 znacajnija bita
jmp kreni
vece: movl %ecx,maksimumg
addl $1,%ebx
movl (%eax,%ebx,4),%ecx
movl %ecx,maksimumd
addl $1,%ebx
jmp kreni
isto: addl $1,%ebx
movl (%eax,%ebx,4),%ecx #sadrzaj nizih 32 bita mogu prebaciti u ecx jer je sadrzaj ecx smesten u maksimumg
cmpl %ecx,maksimumd
je broj
jl zameni
addl $1,%ebx
jmp kreni
zameni: xchgl %ecx,maksimumd #mozemo ih jednostavno zameniti jer sadrzaj u ecx nam nije posle vazan
addl $1,%ebx
jmp kreni
broj: addl $1,%edx #uvecamo samo broj maksimalnih elemenata(posto su maksimalni i isti)
addl $1,%ebx
jmp kreni
krajpp1:
ret
pp2:
pushl %ebp
movl %esp,%ebp
movl 16(%ebp),%eax #adresa prvog clana niza
movl 12(%ebp),%ebx #broj elemenata niza
movl 8(%ebp),%edx #broj maksimalnih elemenata(na pocetku je 1)
xorl %esi,%esi
kreni2: movl (%eax,%esi,4),%ecx #prosledimo prvih 32 bita prvog clana niza u registar ecx
cmpl %ebx,%esi
je krajpp2
cmpl %ecx,maksimumg
jl vece2
je isto2
addl $2,%esi #uvecavamo brojac za 2 jer poredimo samo 32 znacajnija bita
jmp kreni2
vece2: movl %ecx,maksimumg
addl $1,%esi
movl (%eax,%esi,4),%ecx
movl %ecx,maksimumd
addl $1,%esi
jmp kreni2
isto2: addl $1,%esi
movl (%eax,%esi,4),%ecx #sadrzaj nizih 32 bita mogu prebaciti u ecx jer je sadrzaj ecx smesten u maksimumg
cmpl %ecx,maksimumd
je broj2
jl zameni2
addl $1,%esi
jmp kreni2
zameni2: xchgl %ecx,maksimumd #mozemo ih jednostavno zameniti jer sadrzaj u ecx nam nije posle vazan
addl $1,%esi
jmp kreni2
broj2: addl $1,(%edx) #uvecamo samo broj maksimalnih elemenata(posto su maksimalni i isti)
addl $1,%esi
jmp kreni2
krajpp2: movl %ebp,%esp
popl %ebp
ret
.global main
main:
call pp1
push $niz
movl clanova,%ecx
addl %ecx,%ecx
movl %ecx,%edi
push %edi
push $brojmax
call pp2
kraj:
nop
evo koda sa malo komentara za taj zadatak sa maximumom,odradjen je na dva nacina(sa stekom i bez steka),i u dvostrukoj preciznosti je(naravno u jednostrukoj je to mnogo jednostavnije). Mislim da ima par malih greskica ali tu i tamo radi.Potprogram pp1 i pp2 su ubaceni u jedan program pa se pozivaju u istom izvrsavanju.
hvala na pomoci i ako imate jos zadataka(resenih ili ne) i primera stavite ih na ovu temu
[ Vojislav Milunovic @ 08.04.2005. 17:30 ] @
ubaci drugi put [ code ] tag da se lepse vidi kod :) A ne da ja editujem post :))
[ djordje @ 27.04.2005. 01:12 ] @
Sto ne odes kod Laze na konsultacije? On je dobar lik, dace ti sve sto ti treba.
Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|