Microsoft KB Archive/117889

{| = HOWTO: Determine the Amount of Physical Memory Installed =
 * width="100%"|

Article ID: Q117889

The information in this article applies to:
 * Microsoft C/C++ for MS-DOS, version 7.0
 * Microsoft Visual C++ for Windows, versions 1.0, 1.5
 * Microsoft Visual C++ 32-bit Edition, versions 1.0, 2.0, 4.0, 5.0
 * Microsoft Macro Assembler (MASM) for MS-DOS, versions 5.1, 6.0
 * Microsoft MASM for MS-DOS and Windows NT, version 6.11

SUMMARY
You may want to programmatically determine the amount of physical memory installed in a computer. When the computer runs under an operating system that has virtual memory or emulates other operating systems, you may not be able to determine the amount of installed memory from the APIs that the particular operating system provides. In the case of 80x86-based machines, you can obtain that information from the CMOS data.

MORE INFORMATION
"Reading" CMOS data isn't as simple as obtaining a pointer to point to a particular memory location. You must output values to an I/O port and then read values from another port. The Run-Time Library functions "inp" and "outp" can be used in straight C/C++ code; or, you can use the in and out assembly instructions with MASM programs (or with inline assembly in version 6.0 and later of the compiler).

The procedure is straightforward: write values to I/O port 0x70 and read them from 0x71. The values 0x15 and 0x16 are used to get the amount of base memory installed, while 0x17 and 0x18 are used to get the amount of expansion memory (up to 15360 kilobytes) installed. Expansion memory is memory above the 1-MB boundary and should not be confused with expanded memory.

Under Win32, the _inp and _outp functions are system-level (priveleged) instructions. Attempting to use Example 1 of the Sample Code below will result either in unresolved externals at link, _inp and _outp, (when using the C functions) or an Application Error at execution (when using the ASM functions). However, one may simply call the Win32 GlobalMemoryStatus API using a pointer to a MEMORYSTATUS structure to determine the amount of physical memory. See Example 2 below.

Sample Code #1
/* Compile options needed: none

#include   #include 

unsigned short GetBaseMemC; unsigned short GetExpMemC; unsigned short GetBaseMemASM; unsigned short GetExpMemASM;

void main( void ) {  printf( "\nGetBaseMemC returns %u.\n", (unsigned int) GetBaseMemC ); printf( "\nGetExpMemC returns %u.\n", (unsigned int) GetExpMemC ); printf( "\nGetBaseMemASM returns %u.\n",           (unsigned int)GetBaseMemASM ); printf( "\nGetExpMemASM returns %u.\n",            (unsigned int) GetExpMemASM ); }  unsigned short GetBaseMemC {      // using run-time library functions unsigned short base; outp( 0x70, 0x15 ); base = inp( 0x71 ); // retrieve low byte outp( 0x70, 0x16 ); base += inp(0x71) << 8; // retrieve hi-byte, // shift and add to base return base; // return K's of base memory }

unsigned short GetExpMemC {      // using run-time library functions unsigned short extend; outp( 0x70, 0x17 ); extend = inp( 0x71 ); // retrieve low byte outp( 0x70, 0x18 ); extend += inp(0x71) << 8; // retrieve hi-byte, // shift and add to extend return extend; // return K's of expansion memory }

unsigned short GetBaseMemASM {      // using in-line assembly unsigned short base; _asm {             mov dx, 71h // port to read from

mov ax, 15h // lo-byte value out 70h, al // write to port jmp a      // allow bus to settle down a:             in al, dx   // read from port mov byte ptr [base], al // write to lo-byte

mov ax, 16h // hi-byte value out 70h, al // writing jmp b      // settling b:             in al, dx   // reading mov byte ptr [base+1], al // write to hi-byte }

return base; // return K's of base memory }

unsigned short GetExpMemASM {      // using in-line assembly unsigned short extend; _asm {             mov dx, 71h // port to read from

mov ax, 17h // lo-byte value out 70h, al // write to port jmp a      // allow bus to settle down a:             in al, dx   // read from port mov byte ptr [extend], al // write to lo-byte

mov ax, 18h // hi-byte value out 70h, al // writing jmp b      // settling b:             in al, dx   // reading mov byte ptr [extend+1], al // write to hi-byte }

return extend; // return K's of expansion memory }

Sample Code #2
DWORD MyGetMem(void) { MEMORYSTATUS MemoryStatus;
 * 1) include 
 * 2) include 

memset( &MemoryStatus, sizeof(MEMORYSTATUS), 0 ); MemoryStatus.dwLength = sizeof(MEMORYSTATUS);

GlobalMemoryStatus( &MemoryStatus );

return( MemoryStatus.dwTotalPhys ); } void main( void ) {  printf( "Physical memory install = %u bytes.\n", (unsigned int) MyGetMem ); }