[ Ivan Dimkovic @ 08.12.2002. 08:37 ] @
Dakle,

Ako neki ASM guru zna da odgovori na ovo bilo bi jako lepo :)

dakle, problem je sledeci - C projekat je poprilicno veliki i radi se na optimizaciji nekih funkcija mixovanjem asm i c koda.

Simulacija asm-koda u posebnom test.c fajlu (odvojenog od projekata) radi sasvim lepo, ali kada se ubaci u funkciju koja meni treba (u projektu) nastaju vrlo cudni problemi kod adresiranja C varijabli i nizova.

Dakle, imamo globalno definisani niz:

Code:

float  table[16384];


i funkciju:

Code:

int fja()
{

  /* c kod */
  /* ... */

  __asm {
    // .. asm kod
    mov edx,  table
    // ...
  }
}




I sad, kod puca - debugger kasnije kaze da pokusavam da adresiram nesto (indirektno kroz EDX) i EDX je NULA?

EDX uopste ne dobija adresu table, iako u step-by-step modu table pokazuje na memorijsku adresu niza? Posle mov edx, table (i verifikacije da je adresa table OK) edx je i dalje nula u mom projektu?

Zamena table, sa indirektnim pointerom table_ptr (table_ptr = &table[0]) radi posao, ali kasnije kada se ucitava float (fld) dobije se #IND - iako table[n] pokazuje na korektno formatiran float.

Menjanje kompajlera (VC++, ICL) ne pomaze. Napomena - kod radi u posebnom c fajlu koji je test projekat, samo ne radi u velikom projektu?

Da li neko ima ideju? Kod je i386 32-bitni flat model. VC 6.0, ICL 7.0 kao kompajleri?

[ Reljam @ 08.12.2002. 09:52 ] @
Da li mozes da zakacis ovde (mini-)projekat u kome se reprodukuje problem?
[ Ivan Dimkovic @ 08.12.2002. 11:04 ] @
Na zalost - nemam ga ovde kod kuce

U Ponedeljak cu sa posla da attachujem problem.

Ma problem je sto u tom test C fajlu radi sve kako treba, ali kada taj kod prostom copy/paste metodom ubacim u moj projekat - cela stvar prestaje da funkcionise i pojavljuju se ti veoma specificni problemi (sa edx registrom, na primer) :)
[ Bosko @ 09.12.2002. 16:17 ] @
OK, dozvoljava se mesanje assemblera i C-a. da li si obratio mozda paznju na ovo (iz MSDNa):
An __asm block cannot use C or C++ specific operators, such as the << operator. However, operators shared by C and MASM, such as the * operator, are interpreted as assembly-language operators. For instance, outside an __asm block, square brackets ([ ]) are interpreted as enclosing array subscripts, which C automatically scales to the size of an element in the array. Inside an __asm block, they are seen as the MASM index operator, which yields an unscaled byte offset from any data object or label (not just an array). The following code illustrates the difference:

int array[10];

__asm mov array[6], bx ; Store BX at array+6 (not scaled)

array[6] = 0; /* Store 0 at array+12 (scaled) */

The first reference to array is not scaled, but the second is. Note that you can use the TYPE operator to achieve scaling based on a constant. For example, the following statements are equivalent:

__asm mov array[6 * TYPE int], 0 ; Store 0 at array + 12

array[6] = 0; /* Store 0 at array + 12 */

[ Ivan Dimkovic @ 09.12.2002. 18:05 ] @
Sorry.. zaboravih da postujem kod opet dok sam bio na poslu.. sutra :)


Hmm. problem je drugacije prirode - znaci imas instrukciju:

mov edx, table // gde je table float[16384], znaci pointer na table

i kad stepujes u debuggeru u sledecoj liniji je EDX 0

iako TABLE pokazuje na validan pointer.


Problem nestaje ako je table >lokalna< varijabla, ali se onda javljaju neki drugi problemi. Sve u svemu, vrlo cudna situacija.


[ Reljam @ 09.12.2002. 19:08 ] @
E stvarno sam zardjao, trebao sam ovo odmah da napisem.... Evo o cemu se radi:

mov edx, table
je isto sto i
mov edx, table[0]
(prover sa table[0]=1, table[0]=2, itd.)

Ono sto tebi treba je:

lea edx, table

Ono sto takodje mozes da uradis je:

mov edx, OFFSET table

Ali to radi samo za globalne promenljive. Lokalne promenljive nemaju fiksni offset (jer su stack-based), pa zato ne mozes da koristis OFFSET na njima.

Nadam se da ovo pomaze.
[ Ivan Dimkovic @ 09.12.2002. 19:26 ] @
Cini mi se da smo probali sa dword ptr

ali probacu sa LEA sutra - i mislmi da je table pokazivao na adresu &table[0] ako se ne varam (provereno par puta) - ali svejedno provericu jos jednom

Ovaj deo koda nisam ja radio, vec kolega koji se bavi asm-om (meni asm i nije jaca strana :-)


Hvala na odgovorima - probacu sutra to da sredim (mada i nije neki priority...)


Za lokalne promenljive se adresa racuna i preko EBP valjda ako me pamcenje drzi :)
[ Reljam @ 09.12.2002. 20:07 ] @
Ovo sam koristio kao program za testiranje na VC7 - to je valjda to (bez DWORD PTR):

Code:

float table[12123];

int _tmain(int argc, _TCHAR* argv[])
{
    int result;
    table[0]=1;
    _asm
    {
        mov edx, table
        mov result, edx
    }
    printf("mov edx, table = %08X\n",result);

    _asm
    {
        lea edx, table
        mov result, edx
    }
    printf("lea edx, table = %08X\n",result);
    printf("table          = %08X\n",table);
    return 0;
}

Output:


mov edx, table = 3F800000
lea edx, table = 0042C880
table          = 0042C880
[ Mikky @ 12.12.2002. 23:28 ] @
jel problem resen i kako?
[ milanche @ 16.12.2002. 21:26 ] @
Ivane,

mozda je ovo u pitanju:

Ako u vecem projektu upotrebljavas MMX instrukcije, one koriste floating point registre, i na neki nacin 'otkacinju' FP unit od pristupa tim registrima. Naravno, procesor se moze izbaciti iz tog 'okupatorskog' moda tako sto se stavi da po izlasku iz MMX rutine izvrsi 'emms' instrukciju.

Meni su se desavale slicne stvari: napravim funkciju u MMX-u, i kad izadjem iz nje dobijem totalni haos - najprostija floating point instrukcija nije htela da radi kako treba. Setim se i zavrsim MMX kod sa emms, i sve je opet kako treba.

Javi sta si uradio.
[ Ivan Dimkovic @ 16.12.2002. 21:32 ] @
Hmm, kod koristi MMX i SIMD, ali iskljucivo kroz Intel IPP library, pretpostavljam da IPP uvek uradi emms pre izlaza inace bi nastao totalni haos.

Problem jos nije resen, ali nije na nekom prioritetu tako da cu se sa njim pozabaviti sledece godine :)