X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f Received-SPF: None; receiver=nym.alias.net; client-ip=213.250.81.164; envelope-from=; helo=mariah.narpes.com Date: Thu, 20 Apr 2006 10:15:19 +0000 (GMT) From: "A. Wik" Subject: Re: dos buffer In-Reply-To: Message-ID: <20060420034145.K3950@dynamite.narpes.com> References: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Newsgroups: comp.os.msdos.djgpp Organization: none Mail-To-News-Contact: postmaster AT nym DOT alias DOT net Lines: 100 To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Reply-To: djgpp AT delorie DOT com Errors-To: nobody AT delorie DOT com X-Mailing-List: djgpp AT delorie DOT com X-Unsubscribes-To: listserv AT delorie DOT com Precedence: bulk On Wed, 19 Apr 2006, Rod Pemberton wrote: > > Anyway, I've written two examples. They both compile cleanly, but haven't > been thoroughly tested (i.e., possible bugs...). If there are any bugs, > you'll need to sort them out yourself. > > Method 1) > ---- > #include > #include > #include > > #define BUFF 32768 > int main(void) > { > unsigned long base; > /* unsigned short segment,offset; */ > int selector; > char buf[BUFF]; > > /* base is the physical address of the low mem buffer */ > /* selector is used for virtual addressing, i.e., within application space > */ > __dpmi_allocate_dos_memory((BUFF+15)>>4,&selector); > __dpmi_get_segment_base_address(selector,&base); Some nit-picking regarding terminology: "physical" = The primitive, most low-level form of address from a system software (privileged) point of view, and which in the good old days referred to an address output by the CPU onto the bus for referencing main memory, hardware registers (memory mapped IO), the video BIOS, RAM buffers on SCSI/EMS/Ethernet cards, and so on (or non-existent address space). In this day and age, references to "physical" addresses usually never leave the chip (instead landing on the cache). Various CPUs are capable of generating 20-, 24-, 32-, 36-, 40-bit physical addresses or some other size. "logical" = The address formed (explicitly or implicitly) by a 16-bit segment + a 16-, 32-, or 64-bit offset, all depending CPU type and mode. Translated into a linear address through the classical "SHL 4 & ADD"- scheme, or starting from the 286 in protected mode, via the descriptor cache initialised from the GDT and optional LDT table(s) upon loading a segment register. "linear" = The 0-based address space derived from a logical address. From the 8086-80286, and on 386+ in the absence of paging, physical addresses are formed directly by copying/extending/truncating the linear address. With paging enabled on the 386+, translation into physical is instead done according to the page tables, configurable in an ever increasing numbers of ways. At least one of those ways must be sizeable enough to cover the CPU's physical addressing capabilities (or the latter would be rather pointless), however awkward it may be to implement and use (e.g. 36-bit addressing, for using more than 4 GB RAM on 32-bit CPUs would require a scheme of swapping physical memory in and out of the address space, much like the classical 16-bit DOS technologies: EMS, bank-switching, overlays...). "flat" = The memory management scheme in which the code-, stack- and data-segments are all set up with a base address of 0 and a limit including all the memory the program is intended reference. "virtual" = Linear address not equal to the physical address by sign/zero-extension. Might even be swapped out to disk. .. (Corrections/additions welcome.) The __dpmi_physical_address_mapping() function can be used to request a virtual address (range) mapped to a specific physical address, such as the linear frame buffer for a SVGA graphics mode - sample code (error checking omitted): __dpmi_meminfo dmemi; unsigned sel; int st; /* status of calls */ dmemi.size = xres * yres * bpp + 4093 & ~4093; dmemi.address = lfb_addr; st = __dpmi_physical_address_mapping(&dmemi); sel = __dpmi_allocate_ldt_descriptors(1); st = __dpmi_set_segment_base_address(sel, dmemi.address); st = __dpmi_set_segment_limit(sel, dmemi.size-1); -aw