简单地说,你不能。
The mem_lower and mem_upper are obsolete fields, referring to the conventional memory and the extended memory.
Quoting the specifications:
If bit 0 in the
flagsword is set, then themem_*fields are valid.
mem_lowerandmem_upperindicate the amount of lower and upper memory, respectively, inkilobyteskibibytes.Lower memory starts at address 0, and upper memory starts at address 1
megabytemebibyte. The maximum possible value for lower memory is 640kilobyteskibibytes.The value returned for upper memory is maximally the address of the first upper memory hole minus 1
megabytemebibyte. It is not guaranteed to be this value.
The two key aspects of this excerpt are:
flags field needs to be tested before accessing the mem_* fields. mem_lower and mem_upper fields deal with memory holes very badly. Particularly mem_upper holds the size of the first continuous block of extended memory up to the first hole. The second point is important enough to deserve a further discussion.
While the memory itself can be accessed, at the memory controller level1, as a continuous block it is not continuous at the memory subsystem level (what once was the north-bridge and now is the uncore).
The memory subsystem creates holes in the continuous address range assigned to memory either by simply not reclaiming specific sub-ranges - thereby wasting that memory - or by shifting the sub-ranges at higher addresses.
The reasons behind this seemingly strange behaviour have their roots deep in the historical evolution of the IBM PC.
A full discussion is out of topic but a short version can be laid out.
Initially, IBM reserved the first 640KiB of the 1MiB address space for the conventional memory and the remaining 384KiB for mapping the ROMs - including the BIOS ROM.
Note that the memory controller must not respond to read/write accesses above the 640KiB in order for them to get to the ROMs.
When the 1MiB barrier was broken (including or not the HMA at will) the range from 640KiB to 1MiB couldn't be used for backwards compatibility.
This created the first hole: The standard hole.
The 286 had only a 24-bit address bus, thus a 16MiB address space.
At the same time, the ISA bus had already won against the MCA bus and took place in the IBM PC compatible hardware.
Some ISA expansion cards came with expansion ROMs and the standard hole became exhausted, a 1MiB hole was reserved at the end of the 16MiB address space.
I call this hole the ISA hole.
Pretty much the same thing happened with PCI(e) when transitioning from 32-bit to 64-bit systems generating the PCI hole.
In addition to this holes, there are memory ranges that are read/writable but carry precious information laid out by the BIOS - namely the ACPI tables.
Such ranges cannot be carelessly overwritten by the OS and thus must be reported to it.
All of this culminated in the e820 service that instead of returning the memory size (which in the light of the discussion above makes no sense) it returns a memory map made of ranges with their type (available, reserved, reclaimable, bad, NVS).
This is also reflected in the GRUB multiboot_info_t structure fields mmap_* that you should use in place of the mem_lower and mem_upper as indicated in the OSDev wiki.
1周所述的DIMM与秩,银行,列和行数,但存储器控制器通常使此寻址线性和连续访问。