Hi all,
I am participating to Advent of Code ( https://adventofcode.com/ ) this year on a MS-DOS 386SX 16 MHz/2MB RAM/Borland Turbo C++ 3.0 setup as a computing theme. I've got through all the puzzles (1-18) so far on the machine, although in one of the puzzles I find that I would like to squeeze out more memory usage from the machine to optimize runtime performance.
As one possible direction, I am trying to understand how XMS memory works, and maybe use that. There are two good looking sources that I found for reference:
1) http://www.techhelpmanual.com/943-extended_memory_specification__xms_.html
2) http://www.phatcode.net/res/219/files/xms20.txt
It all seems straightforward, and I am able to code up a program based on that, but I have a problem: I don't quite understand how I can access the memory I allocate with XMS function 09h: http://www.techhelpmanual.com/954-xms_09h__allocate_extended_memory_block.html . The function returns a handle to the memory. The function 0Ch can be used to lock the handle and get a 32-bit memory address to that memory block: http://www.techhelpmanual.com/957-xms_0ch__lock_extended_memory_block.html .
However, in real mode, can I even access such a 32-bit memory address directly? (e.g. via a MK_FP(seg, ofs) type of construct, or similar?)
The only functions besides the locking and unlocking I find, are ones that perform a memcpy between conventional memory and XMS memory (identified by a handle). Is that the only way to access XMS memory from a real-mode program? i.e. by memcpying it over to conventional memory, and then back?
Or is there a way to memory map the XMS memory to address space of the real mode program so that it can be directly byte addressed?
I am starting to think that maybe there isn't (after all, real mode is real mode?), and so the handle-based mechanism is the only thing I can get with XMS?
In that case, I am pondering whether EMS would be more appropriate for my use case.
What I am trying to implement is a large hash table cache data structure, where each cache entry is of 6 bytes in size. The hot inner loop of my program reads and writes these cache entries. It feels like if my access to the cache would consist of 6-byte XMS<->conventional memcpy operations, then it might not be that fast to do with XMS? Or is there a direct way to access the XMS memory?
The accesses to the cache memory locations are practically random, so with EMS I suppose I would be switching the active EMS pages on-demand in the page frame if the next memory access would not lie in the same page than the currently mapped one. Since the lookups are random, this would also amount to a lot of page frame switches, which might be quite slow as well.
What would my options be here - what do you think would be the fastest method? (I have already stolen other memory blocks I can find, e.g. video memory. Haven't consumed UMB and HMA yet, but those are also on the list)
Thanks, and have a merry christmas to you all!
I am participating to Advent of Code ( https://adventofcode.com/ ) this year on a MS-DOS 386SX 16 MHz/2MB RAM/Borland Turbo C++ 3.0 setup as a computing theme. I've got through all the puzzles (1-18) so far on the machine, although in one of the puzzles I find that I would like to squeeze out more memory usage from the machine to optimize runtime performance.
As one possible direction, I am trying to understand how XMS memory works, and maybe use that. There are two good looking sources that I found for reference:
1) http://www.techhelpmanual.com/943-extended_memory_specification__xms_.html
2) http://www.phatcode.net/res/219/files/xms20.txt
It all seems straightforward, and I am able to code up a program based on that, but I have a problem: I don't quite understand how I can access the memory I allocate with XMS function 09h: http://www.techhelpmanual.com/954-xms_09h__allocate_extended_memory_block.html . The function returns a handle to the memory. The function 0Ch can be used to lock the handle and get a 32-bit memory address to that memory block: http://www.techhelpmanual.com/957-xms_0ch__lock_extended_memory_block.html .
However, in real mode, can I even access such a 32-bit memory address directly? (e.g. via a MK_FP(seg, ofs) type of construct, or similar?)
The only functions besides the locking and unlocking I find, are ones that perform a memcpy between conventional memory and XMS memory (identified by a handle). Is that the only way to access XMS memory from a real-mode program? i.e. by memcpying it over to conventional memory, and then back?
Or is there a way to memory map the XMS memory to address space of the real mode program so that it can be directly byte addressed?
I am starting to think that maybe there isn't (after all, real mode is real mode?), and so the handle-based mechanism is the only thing I can get with XMS?
In that case, I am pondering whether EMS would be more appropriate for my use case.
What I am trying to implement is a large hash table cache data structure, where each cache entry is of 6 bytes in size. The hot inner loop of my program reads and writes these cache entries. It feels like if my access to the cache would consist of 6-byte XMS<->conventional memcpy operations, then it might not be that fast to do with XMS? Or is there a direct way to access the XMS memory?
The accesses to the cache memory locations are practically random, so with EMS I suppose I would be switching the active EMS pages on-demand in the page frame if the next memory access would not lie in the same page than the currently mapped one. Since the lookups are random, this would also amount to a lot of page frame switches, which might be quite slow as well.
What would my options be here - what do you think would be the fastest method? (I have already stolen other memory blocks I can find, e.g. video memory. Haven't consumed UMB and HMA yet, but those are also on the list)
Thanks, and have a merry christmas to you all!