X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=boot%2Ffreeldr%2Ffreeldr%2Fwindows%2Fwlmemory.c;h=bfa68ab904ed3701280eba5b029cee3562108925;hp=313413e5451adc6d937c6e2589aee07c9cc89855;hb=e4a060ead45b9dc87a64408b6d791ea4a5fef55e;hpb=2597cfe258b768473a744df30227f4067252d9b7;ds=sidebyside diff --git a/boot/freeldr/freeldr/windows/wlmemory.c b/boot/freeldr/freeldr/windows/wlmemory.c index 313413e5451..bfa68ab904e 100644 --- a/boot/freeldr/freeldr/windows/wlmemory.c +++ b/boot/freeldr/freeldr/windows/wlmemory.c @@ -13,15 +13,8 @@ #include #include -extern ULONG TotalNLSSize; extern ULONG LoaderPagesSpanned; -// This is needed because headers define wrong one for ReactOS -#undef KIP0PCRADDRESS -#define KIP0PCRADDRESS 0xffdff000 - -#define HYPER_SPACE_ENTRY 0x300 - PCHAR MemTypeDesc[] = { "ExceptionBlock ", // ? "SystemBlock ", // ? @@ -66,191 +59,30 @@ VOID WinLdrRemoveDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR Descriptor); VOID -WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss); - -// This is needed only for SetProcessorContext routine -#pragma pack(2) - typedef struct - { - USHORT Limit; - ULONG Base; - } GDTIDT; -#pragma pack(4) - -/* GLOBALS ***************************************************************/ - -PHARDWARE_PTE PDE; -PHARDWARE_PTE HalPageTable; - -PUCHAR PhysicalPageTablesBuffer; -PUCHAR KernelPageTablesBuffer; -ULONG PhysicalPageTables; -ULONG KernelPageTables; - -MEMORY_ALLOCATION_DESCRIPTOR *Mad; -ULONG MadCount = 0; - - -/* FUNCTIONS **************************************************************/ +WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG_PTR Pcr, IN ULONG_PTR Tss); BOOLEAN -MempAllocatePageTables() -{ - ULONG NumPageTables, TotalSize; - PUCHAR Buffer; - // It's better to allocate PDE + PTEs contigiuos - - // Max number of entries = MaxPageNum >> 10 - // FIXME: This is a number to describe ALL physical memory - // and windows doesn't expect ALL memory mapped... - NumPageTables = (GetSystemMemorySize() >> MM_PAGE_SHIFT) >> 10; - - DPRINTM(DPRINT_WINDOWS, "NumPageTables = %d\n", NumPageTables); - - // Allocate memory block for all these things: - // PDE, HAL mapping page table, physical mapping, kernel mapping - TotalSize = (1+1+NumPageTables*2)*MM_PAGE_SIZE; - - // PDE+HAL+KernelPTEs == MemoryData - Buffer = MmAllocateMemoryWithType(TotalSize, LoaderMemoryData); - - // Physical PTEs = FirmwareTemporary - PhysicalPageTablesBuffer = (PUCHAR)Buffer + TotalSize - NumPageTables*MM_PAGE_SIZE; - MmSetMemoryType(PhysicalPageTablesBuffer, - NumPageTables*MM_PAGE_SIZE, - LoaderFirmwareTemporary); - - // This check is now redundant - if (Buffer + (TotalSize - NumPageTables*MM_PAGE_SIZE) != - PhysicalPageTablesBuffer) - { - DPRINTM(DPRINT_WINDOWS, "There was a problem allocating two adjacent blocks of memory!"); - } - - if (Buffer == NULL || PhysicalPageTablesBuffer == NULL) - { - UiMessageBox("Impossible to allocate memory block for page tables!"); - return FALSE; - } - - // Zero all this memory block - RtlZeroMemory(Buffer, TotalSize); - - // Set up pointers correctly now - PDE = (PHARDWARE_PTE)Buffer; - - // Map the page directory at 0xC0000000 (maps itself) - PDE[HYPER_SPACE_ENTRY].PageFrameNumber = (ULONG)PDE >> MM_PAGE_SHIFT; - PDE[HYPER_SPACE_ENTRY].Valid = 1; - PDE[HYPER_SPACE_ENTRY].Write = 1; - - // The last PDE slot is allocated for HAL's memory mapping (Virtual Addresses 0xFFC00000 - 0xFFFFFFFF) - HalPageTable = (PHARDWARE_PTE)&Buffer[MM_PAGE_SIZE*1]; - - // Map it - PDE[1023].PageFrameNumber = (ULONG)HalPageTable >> MM_PAGE_SHIFT; - PDE[1023].Valid = 1; - PDE[1023].Write = 1; - - // Store pointer to the table for easier access - KernelPageTablesBuffer = &Buffer[MM_PAGE_SIZE*2]; - - // Zero counters of page tables used - PhysicalPageTables = 0; - KernelPageTables = 0; - - return TRUE; -} - -VOID -MempAllocatePTE(ULONG Entry, PHARDWARE_PTE *PhysicalPT, PHARDWARE_PTE *KernelPT) -{ - //Print(L"Creating PDE Entry %X\n", Entry); - - // Identity mapping - *PhysicalPT = (PHARDWARE_PTE)&PhysicalPageTablesBuffer[PhysicalPageTables*MM_PAGE_SIZE]; - PhysicalPageTables++; - - PDE[Entry].PageFrameNumber = (ULONG)*PhysicalPT >> MM_PAGE_SHIFT; - PDE[Entry].Valid = 1; - PDE[Entry].Write = 1; - - if (Entry+(KSEG0_BASE >> 22) > 1023) - { - DPRINTM(DPRINT_WINDOWS, "WARNING! Entry: %X > 1023\n", Entry+(KSEG0_BASE >> 22)); - } - - // Kernel-mode mapping - *KernelPT = (PHARDWARE_PTE)&KernelPageTablesBuffer[KernelPageTables*MM_PAGE_SIZE]; - KernelPageTables++; - - PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber = ((ULONG)*KernelPT >> MM_PAGE_SHIFT); - PDE[Entry+(KSEG0_BASE >> 22)].Valid = 1; - PDE[Entry+(KSEG0_BASE >> 22)].Write = 1; -} +MempAllocatePageTables(); BOOLEAN MempSetupPaging(IN ULONG StartPage, - IN ULONG NumberOfPages) -{ - PHARDWARE_PTE PhysicalPT; - PHARDWARE_PTE KernelPT; - ULONG Entry, Page; - - //Print(L"MempSetupPaging: SP 0x%X, Number: 0x%X\n", StartPage, NumberOfPages); - - // HACK - if (StartPage+NumberOfPages >= 0x80000) - { - // - // We can't map this as it requires more than 1 PDE - // and in fact it's not possible at all ;) - // - //Print(L"skipping...\n"); - return TRUE; - } + IN ULONG NumberOfPages); - // - // Now actually set up the page tables for identity mapping - // - for (Page=StartPage; Page < StartPage+NumberOfPages; Page++) - { - Entry = Page >> 10; +BOOLEAN +WinLdrMapSpecialPages(ULONG PcrBasePage); - if (((PULONG)PDE)[Entry] == 0) - { - MempAllocatePTE(Entry, &PhysicalPT, &KernelPT); - } - else - { - PhysicalPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT); - KernelPT = (PHARDWARE_PTE)(PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber << MM_PAGE_SHIFT); - } +VOID +MempUnmapPage(ULONG Page); - if (Page == 0) - { - PhysicalPT[Page & 0x3ff].PageFrameNumber = Page; - PhysicalPT[Page & 0x3ff].Valid = 0; - PhysicalPT[Page & 0x3ff].Write = 0; +VOID +MempDump(); - KernelPT[Page & 0x3ff].PageFrameNumber = Page; - KernelPT[Page & 0x3ff].Valid = 0; - KernelPT[Page & 0x3ff].Write = 0; - } - else - { - PhysicalPT[Page & 0x3ff].PageFrameNumber = Page; - PhysicalPT[Page & 0x3ff].Valid = 1; - PhysicalPT[Page & 0x3ff].Write = 1; +/* GLOBALS ***************************************************************/ - KernelPT[Page & 0x3ff].PageFrameNumber = Page; - KernelPT[Page & 0x3ff].Valid = 1; - KernelPT[Page & 0x3ff].Write = 1; - } - } +MEMORY_ALLOCATION_DESCRIPTOR *Mad; +ULONG MadCount = 0; - return TRUE; -} +/* FUNCTIONS **************************************************************/ VOID MempDisablePages() @@ -292,20 +124,7 @@ MempDisablePages() for (Page = StartPage; Page < EndPage; Page++) { - PHARDWARE_PTE KernelPT; - ULONG Entry = (Page >> 10) + (KSEG0_BASE >> 22); - - if (PDE[Entry].Valid) - { - KernelPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT); - - if (KernelPT) - { - KernelPT[Page & 0x3ff].PageFrameNumber = 0; - KernelPT[Page & 0x3ff].Valid = 0; - KernelPT[Page & 0x3ff].Write = 0; - } - } + MempUnmapPage(Page); } } } @@ -365,7 +184,7 @@ MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, MadCount++; // - // Map it (don't map low 1Mb because it was already contigiously + // Map it (don't map low 1Mb because it was already contiguously // mapped in WinLdrTurnOnPaging) // if (BasePage >= 0x100) @@ -379,43 +198,8 @@ MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, } } -#ifdef _M_IX86 -VOID -WinLdrpMapApic() -{ - BOOLEAN LocalAPIC; - LARGE_INTEGER MsrValue; - ULONG APICAddress, CpuInfo[4]; - - /* Check if we have a local APIC */ - __cpuid((int*)CpuInfo, 1); - LocalAPIC = (((CpuInfo[3] >> 9) & 1) != 0); - - /* If there is no APIC, just return */ - if (!LocalAPIC) - return; - - /* Read the APIC Address */ - MsrValue.QuadPart = __readmsr(0x1B); - APICAddress = (MsrValue.LowPart & 0xFFFFF000); - - DPRINTM(DPRINT_WINDOWS, "Local APIC detected at address 0x%x\n", - APICAddress); - - /* Map it */ - HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber - = APICAddress >> MM_PAGE_SHIFT; - HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1; - HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1; - HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].WriteThrough = 1; - HalPageTable[(APIC_BASE - 0xFFC00000) >> MM_PAGE_SHIFT].CacheDisable = 1; -} -#else -VOID -WinLdrpMapApic() -{ - /* Implement it for another arch */ -} +#ifdef _M_ARM +#define PKTSS PVOID #endif BOOLEAN @@ -475,7 +259,7 @@ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, DPRINTM(DPRINT_WINDOWS, "Got memory map with %d entries\n", NoEntries); - // Always contigiously map low 1Mb of memory + // Always contiguously map low 1Mb of memory Status = MempSetupPaging(0, 0x100); if (!Status) { @@ -490,7 +274,7 @@ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, PagesCount = 1; LastPageIndex = 0; LastPageType = MemoryMap[0].PageAllocated; - for(i=1;i= MemoryMapStartPage && @@ -554,25 +338,8 @@ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, return; }*/ - //VideoDisplayString(L"Hello from VGA, going into the kernel\n"); - DPRINTM(DPRINT_WINDOWS, "HalPageTable: 0x%X\n", HalPageTable); - - // Page Tables have been setup, make special handling for PCR and TSS - // (which is done in BlSetupFotNt in usual ntldr) - HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage+1; - HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1; - HalPageTable[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1; - - HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage; - HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1; - HalPageTable[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1; - - // Map APIC - WinLdrpMapApic(); - - // Map VGA memory - //VideoMemoryBase = MmMapIoSpace(0xb8000, 4000, MmNonCached); - //DPRINTM(DPRINT_WINDOWS, "VideoMemoryBase: 0x%X\n", VideoMemoryBase); + /* Map stuff like PCR, KI_USER_SHARED_DATA and Apic */ + WinLdrMapSpecialPages(PcrBasePage); Tss = (PKTSS)(KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT)); @@ -585,42 +352,9 @@ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, List_PaToVa(&LoaderBlock->MemoryDescriptorListHead); #if DBG - { - ULONG *PDE_Addr=(ULONG *)PDE;//0xC0300000; - int j; - - DPRINTM(DPRINT_WINDOWS, "\nPDE\n"); - - for (i=0; i<128; i++) - { - DPRINTM(DPRINT_WINDOWS, "0x%04X | ", i*8); - - for (j=0; j<8; j++) - { - DPRINTM(DPRINT_WINDOWS, "0x%08X ", PDE_Addr[i*8+j]); - } - - DPRINTM(DPRINT_WINDOWS, "\n"); - } - } + MempDump(); #endif - - // Enable paging - //BS->ExitBootServices(ImageHandle,MapKey); - - // Disable Interrupts - _disable(); - - // Re-initalize EFLAGS - __writeeflags(0); - - // Set the PDBR - __writecr3((ULONG_PTR)PDE); - - // Enable paging by modifying CR0 - __writecr0(__readcr0() | CR0_PG); - // Set processor context WinLdrSetProcessorContext(GdtIdt, KIP0PCRADDRESS, KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT)); @@ -696,244 +430,3 @@ WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, return; } -VOID -WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss) -{ - GDTIDT GdtDesc, IdtDesc, OldIdt; - PKGDTENTRY pGdt; - PKIDTENTRY pIdt; - ULONG Ldt = 0; - //ULONG i; - - DPRINTM(DPRINT_WINDOWS, "GDtIdt %p, Pcr %p, Tss 0x%08X\n", - GdtIdt, Pcr, Tss); - - // Kernel expects the PCR to be zero-filled on startup - // FIXME: Why zero it here when we can zero it right after allocation? - RtlZeroMemory((PVOID)Pcr, MM_PAGE_SIZE); //FIXME: Why zero only 1 page when we allocate 2? - - // Get old values of GDT and IDT - Ke386GetGlobalDescriptorTable(&GdtDesc); - __sidt(&IdtDesc); - - // Save old IDT - OldIdt.Base = IdtDesc.Base; - OldIdt.Limit = IdtDesc.Limit; - - // Prepare new IDT+GDT - GdtDesc.Base = KSEG0_BASE | (ULONG_PTR)GdtIdt; - GdtDesc.Limit = NUM_GDT * sizeof(KGDTENTRY) - 1; - IdtDesc.Base = (ULONG)((PUCHAR)GdtDesc.Base + GdtDesc.Limit + 1); - IdtDesc.Limit = NUM_IDT * sizeof(KIDTENTRY) - 1; - - // ======================== - // Fill all descriptors now - // ======================== - - pGdt = (PKGDTENTRY)GdtDesc.Base; - pIdt = (PKIDTENTRY)IdtDesc.Base; - - // - // Code selector (0x8) - // Flat 4Gb - // - pGdt[1].LimitLow = 0xFFFF; - pGdt[1].BaseLow = 0; - pGdt[1].HighWord.Bytes.BaseMid = 0; - pGdt[1].HighWord.Bytes.Flags1 = 0x9A; - pGdt[1].HighWord.Bytes.Flags2 = 0xCF; - pGdt[1].HighWord.Bytes.BaseHi = 0; - - // - // Data selector (0x10) - // Flat 4Gb - // - pGdt[2].LimitLow = 0xFFFF; - pGdt[2].BaseLow = 0; - pGdt[2].HighWord.Bytes.BaseMid = 0; - pGdt[2].HighWord.Bytes.Flags1 = 0x92; - pGdt[2].HighWord.Bytes.Flags2 = 0xCF; - pGdt[2].HighWord.Bytes.BaseHi = 0; - - // - // Selector (0x18) - // Flat 2Gb - // - pGdt[3].LimitLow = 0xFFFF; - pGdt[3].BaseLow = 0; - pGdt[3].HighWord.Bytes.BaseMid = 0; - pGdt[3].HighWord.Bytes.Flags1 = 0xFA; - pGdt[3].HighWord.Bytes.Flags2 = 0xCF; - pGdt[3].HighWord.Bytes.BaseHi = 0; - - // - // Selector (0x20) - // Flat 2Gb - // - pGdt[4].LimitLow = 0xFFFF; - pGdt[4].BaseLow = 0; - pGdt[4].HighWord.Bytes.BaseMid = 0; - pGdt[4].HighWord.Bytes.Flags1 = 0xF2; - pGdt[4].HighWord.Bytes.Flags2 = 0xCF; - pGdt[4].HighWord.Bytes.BaseHi = 0; - - // - // TSS Selector (0x28) - // - pGdt[5].LimitLow = 0x78-1; //FIXME: Check this - pGdt[5].BaseLow = (USHORT)(Tss & 0xffff); - pGdt[5].HighWord.Bytes.BaseMid = (UCHAR)((Tss >> 16) & 0xff); - pGdt[5].HighWord.Bytes.Flags1 = 0x89; - pGdt[5].HighWord.Bytes.Flags2 = 0x00; - pGdt[5].HighWord.Bytes.BaseHi = (UCHAR)((Tss >> 24) & 0xff); - - // - // PCR Selector (0x30) - // - pGdt[6].LimitLow = 0x01; - pGdt[6].BaseLow = (USHORT)(Pcr & 0xffff); - pGdt[6].HighWord.Bytes.BaseMid = (UCHAR)((Pcr >> 16) & 0xff); - pGdt[6].HighWord.Bytes.Flags1 = 0x92; - pGdt[6].HighWord.Bytes.Flags2 = 0xC0; - pGdt[6].HighWord.Bytes.BaseHi = (UCHAR)((Pcr >> 24) & 0xff); - - // - // Selector (0x38) - // - pGdt[7].LimitLow = 0xFFFF; - pGdt[7].BaseLow = 0; - pGdt[7].HighWord.Bytes.BaseMid = 0; - pGdt[7].HighWord.Bytes.Flags1 = 0xF3; - pGdt[7].HighWord.Bytes.Flags2 = 0x40; - pGdt[7].HighWord.Bytes.BaseHi = 0; - - // - // Some BIOS stuff (0x40) - // - pGdt[8].LimitLow = 0xFFFF; - pGdt[8].BaseLow = 0x400; - pGdt[8].HighWord.Bytes.BaseMid = 0; - pGdt[8].HighWord.Bytes.Flags1 = 0xF2; - pGdt[8].HighWord.Bytes.Flags2 = 0x0; - pGdt[8].HighWord.Bytes.BaseHi = 0; - - // - // Selector (0x48) - // - pGdt[9].LimitLow = 0; - pGdt[9].BaseLow = 0; - pGdt[9].HighWord.Bytes.BaseMid = 0; - pGdt[9].HighWord.Bytes.Flags1 = 0; - pGdt[9].HighWord.Bytes.Flags2 = 0; - pGdt[9].HighWord.Bytes.BaseHi = 0; - - // - // Selector (0x50) - // - pGdt[10].LimitLow = 0xFFFF; //FIXME: Not correct! - pGdt[10].BaseLow = 0; - pGdt[10].HighWord.Bytes.BaseMid = 0x2; - pGdt[10].HighWord.Bytes.Flags1 = 0x89; - pGdt[10].HighWord.Bytes.Flags2 = 0; - pGdt[10].HighWord.Bytes.BaseHi = 0; - - // - // Selector (0x58) - // - pGdt[11].LimitLow = 0xFFFF; - pGdt[11].BaseLow = 0; - pGdt[11].HighWord.Bytes.BaseMid = 0x2; - pGdt[11].HighWord.Bytes.Flags1 = 0x9A; - pGdt[11].HighWord.Bytes.Flags2 = 0; - pGdt[11].HighWord.Bytes.BaseHi = 0; - - // - // Selector (0x60) - // - pGdt[12].LimitLow = 0xFFFF; - pGdt[12].BaseLow = 0; //FIXME: Maybe not correct, but noone cares - pGdt[12].HighWord.Bytes.BaseMid = 0x2; - pGdt[12].HighWord.Bytes.Flags1 = 0x92; - pGdt[12].HighWord.Bytes.Flags2 = 0; - pGdt[12].HighWord.Bytes.BaseHi = 0; - - // - // Video buffer Selector (0x68) - // - pGdt[13].LimitLow = 0x3FFF; - pGdt[13].BaseLow = 0x8000; - pGdt[13].HighWord.Bytes.BaseMid = 0x0B; - pGdt[13].HighWord.Bytes.Flags1 = 0x92; - pGdt[13].HighWord.Bytes.Flags2 = 0; - pGdt[13].HighWord.Bytes.BaseHi = 0; - - // - // Points to GDT (0x70) - // - pGdt[14].LimitLow = NUM_GDT*sizeof(KGDTENTRY) - 1; - pGdt[14].BaseLow = 0x7000; - pGdt[14].HighWord.Bytes.BaseMid = 0xFF; - pGdt[14].HighWord.Bytes.Flags1 = 0x92; - pGdt[14].HighWord.Bytes.Flags2 = 0; - pGdt[14].HighWord.Bytes.BaseHi = 0xFF; - - // - // Some unused descriptors should go here - // - - // Copy the old IDT - RtlCopyMemory(pIdt, (PVOID)OldIdt.Base, OldIdt.Limit + 1); - - // Mask interrupts - //asm("cli\n"); // they are already masked before enabling paged mode - - // Load GDT+IDT - Ke386SetGlobalDescriptorTable(&GdtDesc); - __lidt(&IdtDesc); - - // Jump to proper CS and clear prefetch queue -#if defined(__GNUC__) - asm("ljmp $0x08, $1f\n" - "1:\n"); -#elif defined(_MSC_VER) - /* We can't express the above in MASM so we use this far return instead */ - DbgPrint("WinLdrSetProcessorContext: Performing untested far-return\n"); - __asm { - push 8 - push offset resume - retf - resume: - }; -#else -#error -#endif - - // Set SS selector - Ke386SetSs(0x10); // DataSelector=0x10 - - // Set DS and ES selectors - Ke386SetDs(0x10); - Ke386SetEs(0x10); // this is vital for rep stosd - - // LDT = not used ever, thus set to 0 - Ke386SetLocalDescriptorTable(Ldt); - - // Load TSR - Ke386SetTr(KGDT_TSS); - - // Clear GS - Ke386SetGs(0); - - // Set FS to PCR - Ke386SetFs(0x30); - - // Real end of the function, just for information - /* do not uncomment! - pop edi; - pop esi; - pop ebx; - mov esp, ebp; - pop ebp; - ret - */ -}