Всем привет. Вот накатал небольшую прогу, которая тестит всю имеющуюся память, для доступа к которой используется unreal mode. Когда отлаживал программу под vmware, все работало. В реальном ДОСе не пашет. В чем тут может быть дело? Код (Text): ?include "lib/write.h--" ?include "lib/keycodes.h--" byte GDT[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x92,0xCF,0xF0}; byte GDT_Offs[6]={0x00,0x00,0x00,0x00,0x00,0x00}; void main() { struct _MEMBLOCKINFO_{ dword BaseAddrLow; dword BaseAddrHi; dword LengthLow; dword LengthHi; dword Type; }mbi; dword a, b, memsize, mem_block_start, mem_block_size, offset, errors, total_bytes_checked; byte mem_cell; memsize = 0; errors = 0; total_bytes_checked = 0; //-------Go to protected mode-------------------- WriteStr("Go to protected mode...\n"); GDT_Offs=16; EAX=0; AX=DS; EAX<<=4; EAX+=#GDT; DSDWORD[#GDT_Offs+2]=EAX; $LGDT GDT_Offs; DX=8; $PUSH DS $CLI $MOV EAX,CR0 EAX|=1; $MOV CR0,EAX GOTO PROTECTED_MODE_ON; PROTECTED_MODE_ON: GS=DX; FS=DX; ES=DX; DS=DX; AL&=0xFE; $MOV CR0,EAX GOTO REAL_MODE_ON; REAL_MODE_ON: $STI $POP DS AL=0; WriteStr("Now we are in flat mode...\n"); //-------Start memory test----------------------- WriteStr("Checking memory above 1Mb...\n"); $PUSH CS $POP ES DI = #mbi; $XOR ebx,ebx do{ $MOV edx,534D4150h $MOV ecx, sizeof(mbi) $MOV eax,0000E820h $INT 15h a = EAX; if(a!=0x534D4150){ WriteStr("Unexpected error!\n"); WriteStr("Press any key to continue...\n"); BIOSREADKEY(); return; } $PUSH EBX if(mbi.Type==1){ mem_block_start = mbi.BaseAddrLow; mem_block_size = mbi.LengthLow; offset = 0; if(mem_block_start>0xFFFFF){ WriteStr("Checking memory block...\n"); WriteStr("Memory block base address: "); WriteDWordHex(mem_block_start); WriteStr("\nMemory block size: "); WriteDWord(mem_block_size); WriteStr(" bytes\n"); do{ FSBYTE[mem_block_start+offset] = 0xAA; mem_cell = FSBYTE[mem_block_start+offset]; if(mem_cell != 0xAA){ errors++; WriteStr("\nWritten: 0xAA\n"); WriteStr("Read: "); WriteByteHex(mem_cell); }else{ FSBYTE[mem_block_start+offset] = 0x55; mem_cell = FSBYTE[mem_block_start+offset]; if(mem_cell != 0x55){ errors++; WriteStr("\nWritten: 0x55\n"); WriteStr("Read: "); WriteByteHex(mem_cell); } } offset++; total_bytes_checked++; }while(offset<mem_block_size); WriteStr("Memory block checked...\n"); } } $POP EBX b = EBX; }while (b!=0); WriteStr("----------------------------\n"); WriteStr("Total bytes checked: "); WriteDWord(total_bytes_checked); WriteStr("\nErrors: "); WriteDWord(errors); WriteStr("\nPress any key to continue...\n"); BIOSREADKEY(); } Компилятор sphinx c-- 0.238. Скомпилированная прога в аттаче.
в проге вроде все норм попробуй не использовать int 15h и какой у тебя проц? случайно не от фирмы AMD? насколько я помню молодость, некоторые из них unreal режимов ох как не любят
Пробовал на разных процах. Не работает. Как без int 15 определить объем ОЗУ, если ее к примеру 512Mb?
Все нашел глюк, GDT неправильно написал. И объем ОЗУ до 4Gb можно определить функцией E801h int 15h. Короче, получилось так, может кому сгодится: Код (Text): ?include "lib/write.h--" ?include "lib/keycodes.h--" byte GDT[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0xCF,0x92,0x00,0x00}; byte GDT_Offs[6]={0x00,0x00,0x00,0x00,0x00,0x00}; void main(){ dword mem_size1, mem_size2, total_mem, offset, errors, total_bytes_checked; byte mem_cell; $MOV eax,0000E801h $INT 15h mem_size1 = ECX*1024; mem_size2 = EDX*65536; total_mem = mem_size1 + mem_size2; WriteStr("Available memory: "); WriteDWord(total_mem); WriteStr(" bytes\n"); //-------Go to protected mode-------------------- WriteStr("Go to protected mode...\n"); GDT_Offs=16; EAX=0; AX=DS; EAX<<=4; EAX+=#GDT; DSDWORD[#GDT_Offs+2]=EAX; $LGDT GDT_Offs; DX=8; $PUSH DS $CLI $MOV EAX,CR0 EAX|=1; $MOV CR0,EAX GOTO PROTECTED_MODE_ON; PROTECTED_MODE_ON: GS=DX; FS=DX; ES=DX; DS=DX; AL&=0xFE; $MOV CR0,EAX GOTO REAL_MODE_ON; REAL_MODE_ON: $STI $POP DS AL=0; WriteStr("Now we are in flat mode...\n"); $IN al, 92h $OR al, 2 $OUT 92h, al //-------Start memory test----------------------- WriteStr("Checking memory above 1Mb...\n"); offset = 0x100000; errors = 0; total_bytes_checked = 0; do{ FSBYTE[offset] = 0xAA; mem_cell = FSBYTE[offset]; if(mem_cell != 0xAA){ errors++; WriteStr("\nWritten: 0xAA\n"); WriteStr("Read: "); WriteByteHex(mem_cell); }else{ FSBYTE[offset] = 0x55; mem_cell = FSBYTE[offset]; if(mem_cell != 0x55){ errors++; WriteStr("\nWritten: 0x55\n"); WriteStr("Read: "); WriteByteHex(mem_cell); } } offset++; total_bytes_checked++; }while(offset<total_mem); WriteStr("----------------------------\n"); WriteStr("Total bytes checked: "); WriteDWord(total_bytes_checked); WriteStr("\nErrors: "); WriteDWord(errors); WriteStr("\nPress any key to continue...\n"); BIOSREADKEY(); }
Объем ОЗУ определяется так: 1 counter = 0x100000 2 записываем байт в адрес [counter] 3 читаем байт из адреса [counter] 4 это тот байт что мы записали? 5 да - память существует, нет - память не существует, останавливаемся (прыгаем на строку 8) 6 counter = counter + 1 (чтоб побыстрее можно прыгать через мегабайт +0x100000) 7 прыгаем на строку 2, продолжаем цикл 8 count - количество памяти на компе Так объем ОЗУ определяет BIOS и операционные системы А чтоб протестить память желательно пробежаться по ней 2-3 раза и записывать разные байты