📄 mmodels.faq
字号:
---------QUESTION:--------- I haven't been able to find anything that explains the memory models to mysatisfaction.-------ANSWER:------- It's pretty simple. 80x86 CPUs (in real, as opposed to protected or flat,mode) form 32-bit segmented addresses of the form ssss:oooo, where ssss isthe 16-bit segment address and oooo is the 16-bit offset address. The "real"address is (16 * ssss) + oooo, so the actual range is limited to only 20 bitsof significance. Given this fact, the code still has to access data and program memory. Ithas to access program memory in order to call other functions, performconditional branches, etc. It also obviously has to access the data stored inmemory. To facilitate memory access, the 80x86 CPUs provide segment registers, theprinciple ones being the CS and DS registers which hold the segment values ofthe Code Segment and Data Segment respectively. If your code or data are small enough to each fit within 64K, your programcan become more efficient by simply setting the segment registers once andthen forgetting them for the rest of the program's execution. Internally,whenever your programs needs data, it only specifies a 16-bit offset and thesegment is provided by the DS register. Similarly, when you need to callanother function, you only need to provide a 16-bit offset address and itssegment is provided by the CS register. If either your code or your data outgrow the bounds of a single 64Ksegment, your program is then forced to access them with a full 32-bitssss:oooo address. A further complication is if any of your data objectsoverflow a 64K segment. In such a case, you have to readjust your DS registerevery time you access such a data object based on where within the object youneed to access. This is where memory models come in.Tiny: Code and Data both fit within the same 64K segment.Small: Code and Data each fit within their own 64K segments.Compact: Code fits in a 64K segment but Data doesn't.Medium: Data fits in a 64K segment but Code doesn't.Large: Neither Code nor Data will fit in a 64K segment.Huge: Same as large, but individual objects may be over 64K.(Note: Symantec/Zortech C++ breaks several of the above rules; 1) its Tinymodel works just like Small model, 2) Huge model isn't suported, 3)additional features are supported as additional memory models - V model forsmart overlays, X model for 32-bit extended DOS applications, R model for16-bit extended DOS apps, etc.)---------QUESTION:--------- How do memory models relate to near and far pointers? What's thedifference? And what are the various _fmem???() and _fstr???() functions usedfor?-------ANSWER:------- It's simple once you understand the concept of segment registers. A nearpointer is simply a pointer that doesn't require a segment to be specified. Afar pointer includes both a segment and offset. Relating this to the previous question, in Small and Tiny models, allpointers are near pointers. In Large and Huge models, all pointers are farpointers. In Compact model, function (code segment) pointers are nearpointers and data pointers are far pointers. In Medium model, function (codesegment) pointers are far pointers and data pointers are near pointers. Sometimes, however, you may need to use a far pointer in a memory modelthat otherwise uses near pointers. Some examples would be:1. Your program is written in Tiny, Small, or Medium model, yet you want to access the PC's video memory which requires specifying the video RAM segment to use. You would have to specify the video RAM address using a far pointer. Since standard library funtions assume that all pointers conform to the current memory model, functions such as memcpy() will not work. What's needed in this example would be a memcpy() work-alike that uses explicit far pointers - in other words, you need to use _fmemcpy(). Note that in Compact, Large, or Huge memory models, such functions already expect far pointers and so the use of the _fstr???() and _fmem???() functions is unnecessary, although benign.2. You're writing an interrupt service routine (ISR). All ISR's specify a far function pointer. This is why you'll always see them specified in portable code in a manner similar to this:extern void (_interrupt _far *oldint9)(void);---------QUESTION:--------- I always have used the tiny memory model, and when I use libraries I usethe small memory model because that's as small as these particular librariessupport.-------ANSWER:------- The difference between Tiny and Small models is in the startup code - thelibraries for each are identical since each assumes that CS and DS will beset once and for all by the startup code.---------QUESTION:--------- What I want to know is how big does my program have to be before I wouldstart using a larger memory model? So far small has been more than adequateeven though I consider some of my programs quite large. Although maybe notnearly as large as I think.-------ANSWER:------- Maybe not. :-) You'll know when 1) you begin to get linker errors aboutsegment overflows, 2) you get runtime errors when memory allocation functionsbegin failing. For folks needing to port code from other systems, Large or Huge are theticket since they make no assumptions about addressing. Using Large or Hugemodel is always safe, but will obviously pay a run-time performance penalty.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -