torek@elf.ee.lbl.gov (Chris Torek) (03/29/91)
In article <1991Mar28.190320.10724@cbnewsj.att.com> asd@cbnewsj.att.com (Adam S. Denton) writes: >... consider the following code, which is ubiquitous >in MSDOS: (my apologies for including platform-specific code here) > > void far *p; > ... > p = (void far *) 0xFFFFE000; > >when IMHO the proper abstraction should be > > void far *p; > ... > p = MK_FP(0xFFFFu, 0xE000u); Actually, I have no idea what (if anything) might be at FFFF:E000, but to consider another example---screens---a `better' way to write this is something like: union screendata { short sd_xc; /* extended character */ struct { char sd_ch; /* character */ char sd_attr; /* attribute */ } sd_un; }; #define SCREENSEG 0xe800 /* or whatever */ #define SCREENBASE ((union screendata far *)MK_FP(SCREENSEG, 0)) or even just #define SCREENBASE ((union screendata far *)0xe8000000) or whatever. The point is to hide the fact that this is an `absolute address', and the way it is built, as much as possible, and to use a meaningful symbol rather than a magic number. That way when the next instance of the system has the screen at a different address, you need only change one `define' and maybe add some initialization code: extern union screendata far *screenbase; #define SCREENBASE screenbase All of this should be used only to build the lowest level abstraction (a `screen' would then become something you could print to, say) on which you build the next level (windows, perhaps). -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov