Welchen Wert bei Initialisierung für Code- und Datensegmente bei VM86 Task?



  • Hallo zusammen,

    EHCI hat erstmal Pause 🙂

    Mein Multitasking läuft sehr gut. Ich möchte nun gern eine VM86 Task hinzufügen,
    die mir lediglich den Buchstaben "V" rechts oben auf dem Schirm in einer Endlos-
    schleife ausgibt (somit erspare ich mir hoffentlich irgendwelche Exceptions)

    Mein Code dazu ist wie folgt:

    svga:	mov di, 0xA000
    		mov es, di
    		mov di, 158d
    		mov al, "V"
    		stosb
    		jmp svga
    

    Dazu nutze ich den selben Code wie beim erstellen einer "normalen" Task.
    Lediglich Code- und alle Segementregister werden mit 0 initialisiert.
    Die Anfangsandresse ist fest 803Ah

    Mein Flagregister wird wie bei euch auch mit 020202h initialisiert.
    ESP wird beim Taskswitch mit 7F58h geladen. Alles Werte in den ersten
    64 Kbyte vom RAM.

    Paging habe ich dafür ausgeschaltet.

    Wie nicht anders zu erwarten gehts natürlich nichts 😕
    Ich habe auch schon sämtliche Kombinationen mit Segementdescriptoren (PL3) usw.
    versucht.

    Hat vielleicht hier jemand einen Tipp für mich woran es liegen könnte?

    Nicky



  • Code als 16-bit-code assembliert?



  • mov al, "V" <-- sollte wohl 'V' sein, oder ist nasm das egal?



  • Hallo,

    Code ist 16bit.
    Das mit den Anführungszeichen ist egal...

    Müssen alle Segmentregister mit 0 initialisiert werden? Also keine
    Segmentdescriptoren verwenden?

    Mein VM86 Stack sieht nach der Erstellung so aus:

    Flags:		0x20202h		;Adresse 32600d
    CS:		    0x0h
    IP:		    0x80A3h
    
    EAX:		0x0h
    EBX:		0x0h
    ECX;:		0x0h
    EDX:		0x0h
    EBP:		0x0h
    ESI:		0x0h
    EDI:		0x0h
    
    SS:		0x0h
    FS:		0x0h
    GS:		0x0h
    ES:		0x0h
    DS:		0x0h			;Adresse 32540d
    

    ESP bekommt nach Taskswitch 32540d zugewiesen.

    Nicky


  • Mod

    was sagt der bochs debugger?



  • Erhard Henkes schrieb:

    was sagt der bochs debugger?

    Hallo Erhard,

    habe nur VBOX und VPC. Mit Bochs komme ich nicht zurecht.
    Der IRQ13 wird immer aufgerufen.
    Eip zeigt dann auf 0x80A3

    Nicky



  • VBox hat auch einen Debugger: http://www.lowlevel.eu/wiki/VirtualBox#Debugger


  • Mod

    IRQ 13 könnte #GP sein und vlt. auch sensitive opcode error.



  • Hallo zusammen,

    der Debugger gibt folgenden aus:

    00:05:02.657611 Guest CPUM (VCPU 0) state:
    00:05:02.657626 eax=002035f7 ebx=00007fbc ecx=00000000 edx=00000000 esi=01000008 edi=01000004
    00:05:02.657629 eip=002010e4 esp=00007f14 ebp=0007fff8 iopl=0 nv up di pl nz na po nc
    00:05:02.657631 cs={0008 base=0000000000000000 limit=ffffffff flags=0000c09b} dr0=00000000 dr1=00000000
    00:05:02.657636 ds={0010 base=0000000000000000 limit=ffffffff flags=0000c093} dr2=00000000 dr3=00000000
    00:05:02.657639 es={0010 base=0000000000000000 limit=ffffffff flags=0000c093} dr4=00000000 dr5=00000000
    00:05:02.657642 fs={0010 base=0000000000000000 limit=ffffffff flags=0000c093} dr6=ffff0ff0 dr7=00000400
    00:05:02.657645 gs={0010 base=0000000000000000 limit=ffffffff flags=0000c093} cr0=00000011 cr2=00000000
    00:05:02.657647 ss={0010 base=0000000000000000 limit=ffffffff flags=0000c093} cr3=00033000 cr4=00000000
    00:05:02.657650 gdtr=0000000000021000:0028 idtr=0000000000020000:0188 eflags=00000046
    00:05:02.657653 ldtr={0000 base=00000000 limit=0000ffff flags=00000082}
    00:05:02.657654 tr ={0000 base=00000000 limit=0000ffff flags=0000008b}

    EIP hängt in der Warteschleife fest die nach dem IRQ13 aufgerufen wird

    ;-------------------------------------------------------------------------------------------------------
    				;Programmende = Endlosschleife
     000000E4			progr_ende:
     000000E4			@@:
     000000E4  90				nop
     000000E5  EB FD			jmp @b
    

    Der Fehlerverursachende Befehl liegt bei 0xDC6 in Zeile 7.
    Und der Fehlercode = 0x20h

    00000DBB  66| 8E D0	      C 	mov ss, ax
    			      C 	
    			      C 	invoke GetNextESP, esp
     00000DC4  8B E0	      C 	mov esp, eax
    			      C 
    			      C 	
     00000DC6  17		      C 	pop ss
     00000DC7  0F A9	      C 	pop gs
     00000DC9  0F A1	      C 	pop fs
     00000DCB  07		      C 	pop es
     00000DCC  1F		      C 	pop ds
    			      C 	
     00000DCD  5D		      C 	pop ebp
     00000DCE  5F		      C 	pop edi
     00000DCF  5E		      C 	pop esi
     00000DD0  5A		      C 	pop edx
     00000DD1  59		      C 	pop ecx
     00000DD2  5B		      C 	pop ebx
     00000DD3  58		      C 	pop eax
    			      C 	
    			      C 	
     00000DD4  50		      C 	push eax
     00000DD5  FF 05 00000335 R   C 		inc time_counter
     00000DDB  B0 20	      C 		mov al, 020h
     00000DDD  E6 20	      C 		out 020h, al
     00000DDF  58		      C 	pop eax
     00000DE0  CF		      C 	iretd
     00000DE1		      C IRQ32 endp
    

    Dies deutet wohl darauf hin das er das Segmentregister mit 0x23h nicht laden kann. Die selben Adressen/Fehlercodes kommen auch beim Versuch die Segmentregister mit NULL
    zu laden.

    gdttabelle:			;0
       142 00000081 00000000                		dd 0
       143 00000085 00000000                		dd 0
       144                                  CODE:				;8
       145 00000089 FFFF                    		dw 0xFFFF
       146 0000008B 0000                    		dw 0                 		
       147 0000008D 00                      		db 0                 			
       148 0000008E 9A                      		db 10011010b
       149 0000008F CF                      		db 11001111b			;DB und G Bit gesetzt
       150 00000090 00                      		db 0
       151                                  DATEN:				;16		
       152 00000091 FFFF                    		dw 0xFFFF
       153 00000093 0000                    		dw 0					
       154 00000095 00                      		db 0		                 	
       155 00000096 92                      		db 10010010b
       156 00000097 CF                      		db 11001111b			;DB und G Bit gesetzt
       157 00000098 00                      		db 0		
       158                                  CODE3:				;24
       159 00000099 FFFF                    		dw 0xFFFF
       160 0000009B 0000                    		dw 0                 		
       161 0000009D 00                      		db 0                 			
       162 0000009E FA                      		db 11111010b
       163 0000009F 00                      		db 0b			;DB und G Bit nicht gesetzt
       164 000000A0 00                      		db 0
       165                                  DATEN3:				;32		
       166 000000A1 FFFF                    		dw 0xFFFF
       167 000000A3 0000                    		dw 0					
       168 000000A5 00                      		db 0		                 	
       169 000000A6 F2                      		db 11110010b
       170 000000A7 00                      		db 0b			;DB und G Bit nicht gesetzt
       171 000000A8 00                      		db 0		
       172                                  GDT:
       173 000000A9 2800                    .gdt_limit 	dw $ - gdttabelle		;5 * 8 = 40 Byte
       174 000000AB [81000000]              .gdt_base	dd gdttabelle			;
    

    Ich benutze kein Taskregister und mein Programm läuft auf PL0.

    Hat jemand eine Idee was ich machen könnte?

    Nicky 😕


  • Mod

    in PrettyOS sieht das so aus am Anfang:

    // "Segment Present" bit 7
    #define VALID                0x80
    
    // "Deskriptor Privilege Level" bit 6:5
    #define RING_0               0x00
    #define RING_1               0x20
    #define RING_2               0x40
    #define RING_3               0x60
    
    // "Segment" bit 4
    #define SYSTEM               0x00
    #define CODE_DATA_STACK      0x10
    
    // "Descriptor Type" bit 3:1
    #define DATA_READ_ONLY       0x0  // ....000.
    #define DATA_READ_WRITE      0x2  // ....001.
    #define STACK_READ_ONLY      0x4  // ....010.
    #define STACK_READ_WRITE     0x6  // ....011.
    #define CODE_EXEC_ONLY       0x8  // ....100.
    #define CODE_EXEC_READ       0xA  // ....101.
    #define CODE_EXEC_ONLY_CONF  0xC  // ....110.
    #define CODE_EXEC_READ_CONF  0xE  // ....111.
    
    // "Segment Accessed" bit 0
    #define SEGM_ACCESSED        0x1
    
    /**********************/
    /*  Parameter "gran"  */
    /**********************/
    
    // "granularity"            bit 7
    #define _BYTE_              0x00
    #define _4KB_               0x80
    
    // "Default Operation Size" bit 6
    #define USE16               0x00
    #define USE32               0x40
    
    // Defines a GDT entry
    typedef struct
    {
        uint16_t limit_low;
        uint16_t base_low;
        uint8_t  base_middle;
        uint8_t  access;
        uint8_t  granularity;
        uint8_t  base_high;
    } __attribute__((packed)) GDTentry_t;
    
    typedef struct
    {
        uint16_t limit;
        uint32_t base;
    } __attribute__((packed)) GDTptr_t;
    
    void gdt_install(void)
    {
        GDTptr_t gdt_register;
    
        // Setup the GDT pointer and limit
        gdt_register.limit = (sizeof(GDTentry_t) * NUMBER_GDT_GATES)-1;
        gdt_register.base  = (uint32_t)&gdt;
    
        // GDT GATES -  desriptors with pointers to the linear memory address
        gdt_setGate(0,0,0,0,0); // NULL descriptor
    
        //          num base limit    access                                              gran
        gdt_setGate(1,  0,   0xFFFFF, VALID | RING_0 | CODE_DATA_STACK | CODE_EXEC_READ,  _4KB_ | USE32);
        gdt_setGate(2,  0,   0xFFFFF, VALID | RING_0 | CODE_DATA_STACK | DATA_READ_WRITE, _4KB_ | USE32);
        gdt_setGate(3,  0,   0xFFFFF, VALID | RING_3 | CODE_DATA_STACK | CODE_EXEC_READ,  _4KB_ | USE32);
        gdt_setGate(4,  0,   0xFFFFF, VALID | RING_3 | CODE_DATA_STACK | DATA_READ_WRITE, _4KB_ | USE32);
    
        tss_write(5, 0x10, 0x0); // num, ss0, esp0
        gdt_flush(&gdt_register);
        tss_flush();
    }
    
    void gdt_setGate(int32_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran)
    {
        // Setup the descriptor base address
        gdt[num].base_low    =  base & 0xFFFF;
        gdt[num].base_middle = (base >> 16) & 0xFF;
        gdt[num].base_high   = (base >> 24) & 0xFF;
    
        // Setup the descriptor limits
        gdt[num].limit_low   = limit & 0xFFFF;
        gdt[num].granularity = (limit >> 16) & 0x0F;
    
        // Finally, set up the granularity and access flags
        gdt[num].granularity |= (gran & 0xF0);
        gdt[num].access      = access;
    }
    
    // Initialise our task state segment structure.
    void tss_write(int32_t num, uint16_t ss0, uint32_t esp0)
    {
        // Firstly, let's compute the base and limit of our entry into the GDT.
        uint32_t base = (uint32_t)&tss;
        uint32_t limit = sizeof(tss); //http://forum.osdev.org/viewtopic.php?f=1&t=19819&p=155587&hilit=tss_entry#p155587
    
        // Now, add our TSS descriptor's address to the GDT.
        gdt_setGate(num, base, limit, 0xE9, 0x00);
    
        tss.ss0  = ss0;  // Set the kernel stack segment.
        tss.esp0 = esp0; // Set the kernel stack pointer.
    
        tss.cs   = 0x08;
        tss.ss = tss.ds = tss.es = tss.fs = tss.gs = 0x10;
      #ifdef _DIAGNOSIS_
        tss_log(&tss);
      #endif
    }
    

Anmelden zum Antworten