HOWTO: Determine the Amount of Physical Memory InstalledLast reviewed: October 3, 1997Article ID: Q117889 |
The information in this article applies to:
SUMMARYYou 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 <conio.h> #include <stdio.h> 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
#include <stdio.h> #include <windows.h>DWORD MyGetMem(void) { MEMORYSTATUS MemoryStatus; 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() ); }
REFERENCESThe "Programmer's PC Sourcebook," 2nd ed., published by Microsoft Press, contains more information about the layout of the CMOS data area. The "Win32 Programmer's Reference" contains more information on the GlobalMemoryStatus function as does the Functions Reference of the SDKs : Win32 SDK : Win32 book included in the Visual C++ version 4.0 Books Online. The "Run-Time Library Reference Manual" contains more information about the inp and outp functions. Keywords : CLngIss Version : MS- DOS:5.1,6.0,6.11,7.0;WIN3X:1.0,1.5;WINNT:1.0,2.0,4.0,5.0,6.11; Platform : MS-DOS NT WINDOWS Issue type : kbhowto |
================================================================================
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |