memset Funktion stürzt ab



  • Hi,

    ich habe einen kleinen Kernel in Assembler und C geschrieben.
    Jetzt bin ich gerade dabei, die IDT zu laden. Aber jedesmal wenn ich meinen kernel wie gewohnt mit qemu öffne, stürzt dieser ab. (Vorher kompilier/assemblier und linke ich ihn natürlich)

    Ich konnte das Problem bereits auf eine C-Funktion einschränken:

    void memset (void *pDest, char cValue, unsigned int iCount)
    {
    	asm (
    		"push 	%ebp;"	
    		"movl 	%esp, %ebp;" 	
    		"push 	%eax;" 	
    		"push 	%ecx;"	
    		"push 	%esi;" 	
    		"movl 	8(%ebp), %edi;"
    		"movl 	12(%ebp), %eax;"
    		"movl 	16(%ebp), %ecx;"
    		"rep 	stosb;"
    		"pop 	%esi;"
    		"pop 	%ecx;"
    		"pop 	%eax;"
    		"movl 	%ebp, %esp;"
    		"pop 	%ebp;"
    		"ret 	;" );
    }
    

    Die C-Funktion besteht ganz aus Inline-Assembler (daher hab ich ins Assembler-Forum gepostet; ich hoffe das ist okay so...) in AT&T-Syntax, welchen ich nicht gewohnt bin 😉 Ich muss ihn allerdings nutzen, da ich den gcc benutzte.

    Wenn qemu abstürzt, bekomme ich folgendes:

    qemu: fatal: triple fault
    EAX=00000000 EBX=0002d8e4 ECX=0000000f EDX=00000002
    ESI=00054527 EDI=00301038 EBP=001fff98 ESP=001fff98
    EIP=0002d89c EFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
    ES =0010 00000000 ffffffff 00cf9300
    CS =0008 00000000 ffffffff 00cf9a00
    SS =0010 00000000 ffffffff 00cf9300
    DS =0010 00000000 ffffffff 00cf9300
    FS =0010 00000000 ffffffff 00cf9300
    GS =0010 00000000 ffffffff 00cf9300
    LDT=0000 00000000 0000ffff 00008000
    TR =0000 00000000 0000ffff 00008000
    GDT= 00101040 00000017
    IDT= 00000000 000003ff
    CR0=60000011 CR2=00000000 CR3=00000000 CR4=00000000
    CCS=00000000 CCD=00000053 CCO=ADDB
    FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
    FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
    FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
    FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
    FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
    XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
    XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
    XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
    XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
    Aborted

    Was mich ein bisschen erstaunt ist der Instruction Pointer, denn den Wert 0002d89c kann ich keiner Code-Stelle der memtest-Funktion zuordnen.

    Dissamblieren mit objdump ergab folgendes:

    001003d0 <memset>:
    1003d0: 55 push %ebp
    1003d1: 89 e5 mov %esp,%ebp
    1003d3: 83 ec 04 sub $0x4,%esp
    1003d6: 8b 45 0c mov 0xc(%ebp),%eax
    1003d9: 88 45 fc mov %al,-0x4(%ebp)
    1003dc: 55 push %ebp
    1003dd: 89 e5 mov %esp,%ebp
    1003df: 50 push %eax
    1003e0: 51 push %ecx
    1003e1: 56 push %esi
    1003e2: 8b 7d 08 mov 0x8(%ebp),%edi
    1003e5: 8b 45 0c mov 0xc(%ebp),%eax
    1003e8: 8b 4d 10 mov 0x10(%ebp),%ecx
    1003eb: f3 aa rep stos %al,%es:(%edi)
    1003ed: 5e pop %esi
    1003ee: 59 pop %ecx
    1003ef: 58 pop %eax
    1003f0: 89 ec mov %ebp,%esp
    1003f2: 5d pop %ebp
    1003f3: c3 ret
    1003f4: c9 leave
    1003f5: c3 ret

    Wisst ihr was ich da falsch mache?

    Danke im Voraus



  • boom schrieb:

    Wisst ihr was ich da falsch mache?

    du hast dich nicht genug im umgang mit dem gcc inline assembler beschäftigt 🙂
    wozu den ganzen funktionsrahmen in assembler, wenn gcc das sowieso schon übernimmt, in dem du alles in eine funktion packst. also den ganzen stackkram rausnehmen. ein 'ret' hat da auch nichts zu suchen. copy&paste ist bei inline assembler nicht 😉
    hier mal ein beispiel wie eine swab funktion mit inline assembly aussehen kann, weil ichs gerade zur hand habe:

    void swab32(void* val)
    {
        asm ("mov %0, %%rsi\n"
             "mov %0, %%rdi\n"
             "lodsl\n"
             "bswap %%eax\n"
             "stosl\n"
             : // no output variable
             :"r"(val)
             :"%eax","%rsi","%rdi" );
    }
    

    ganz wichtig ist auch am schluss die 'clobber list'. les' dich da mal ein 😉



  • Okay, danke für den Tipp 😉

    Ich hab jetzt

    void memset (void *pDest, char cValue, unsigned int iCount)
    {
    	asm (
    		"movl 	%0, %%edi;"
    		"movl 	%1, %%eax;"
    		"movl 	%2, %%ecx;"
    		"rep 	stosb;"
    	: : "r" (pDest), "r" (cValue & 0xFFFFFFFF), "r" (iCount) : "%edi", "%eax", "%ecx");
    }
    

    und das scheint zu funktionieren.



  • na also, geht doch 🙂

    wobei ich das:

    cValue & 0xFFFFFFFF
    

    nicht nachvollziehen kann 😕



  • das habe ich dazugefügt, da es ohne das "& 0xFFFFFFFF" nicht geht.
    Ich glaube das liegt daran, dass ich ja in das eax-Register schreibe, und da passen ja 4 Byte rein. Deshalb versuche ich mit dem "& 0xFFFFFFFF" den char länger zu machen, damit er da rein passt.



  • dann gebe doch die richtige breite beim kopieren an, entweder explizit durch movb, oder implizit dur das kopieren nach al. hier ist beides:

    void memset (void *pDest, char cValue, unsigned int iCount)
    {
        asm (
            "movl     %0, %%edi;"
            "movb     %1, %%al;"
            "movl     %2, %%ecx;"
            "rep     stosb;"
        : : "r" (pDest), "r" (cValue), "r" (iCount) : "%edi", "%eax", "%ecx");
    }
    

  • Mod

    gcc-inline-Assemblercode, der mit mov beginnt oder aufhört, dürfte immer suboptimal sein - damit machte man ja den größten Vorteil dieser Methode zunichte.

    void memset (void *pDest, char cValue, unsigned int iCount)
    {
        asm ( "\trep stosb\n" : : "D" (pDest), "a" (cValue), "c" (iCount));
    }
    


  • hier stand müll *schäm*


  • Mod

    sothis_ schrieb:

    ich kann keinen unterschied erkennen 😉

    Ich auch nicht. Ist ja auch nicht der Code, der zum inline-Assembler gehört.



  • camper schrieb:

    sothis_ schrieb:

    ich kann keinen unterschied erkennen 😉

    Ich auch nicht. Ist ja auch nicht der Code, der zum inline-Assembler gehört.

    ich habe noch nicht genug kaffee im blut 😃


Anmelden zum Antworten