[ 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.