• Please review our updated Terms and Rules here

How to load memory when BX register wraps around in 8088 CPU?

NicolasF

Experienced Member
Joined
Jun 28, 2006
Messages
255
Location
Argentina
Hi, I need to code a routine that will load up to 65535 (FFFFh) bytes into memory location pointed by ES:BX. The problem that I'm facing is that I will have to change both ES and BX depending on their values. If ES=0000h and BX=4000h and I want to load FFFFh bytes then I have to modify ES when BX wraps around, but if I only want to load 1000h then I'll be ok if I only increase BX. Is there any addressing mode that will do this for me? or do I have to implement this kind of logic?

This code only works if BX wont wrap around.

Code:
	 mov ax, 0
	 mov es, ax
	 mov bx, 04000h
	 mov cx, 0ffffh
	 mov al, 055h
load_mem:
	 mov es:[bx], al
	 inc bx
	 dec cx
	 jnz load_mem
 
No, you have to modify the segment register. In you case, set ES to 0400h and BX to 0.

It gets a little more involved when you want to store 65,535 bytes on a boundary that doesn't start on a paragraph.

This goes to one of my problems with the 8086 architecture that I complained about in 1980. Manipulating large data structures is painful. On the 68K it's straightforward.
 
Yes. More generically, the rule to keep in mind is that (ES + BX>>4):0000 points to the same address as ES:BX... as long as the last nybble of BX is 0.

The last time I had to fill some 400K of RAM (*quickly*), in chunks much smaller than 64K, I had my inner loops always assume an offset of 0 and did all arithmetic on the segment register exclusively, outside the loop.

I also feel compelled to point out that your inner load_mem code is, ahem, non-efficient. But you didn't ask, so I'll assume it's just a placeholder for real code. ;)
 
When handling large data structures, I find that it's convenient to reduce offsets to <32K; you avoid boundary issues with little additional overhead.

OP: If you want to fill memory fast, consider "rep stos"--and words are faster than bytes.
 
Hi,

Are you sure you want to copy FFFFh and not 10000h ?


Your code, to write to the Address 4000h in 32bit can be simplified like this:
Code:
	 mov ax,00400h
	 mov es, ax
	 xor di,di
         mov cx,4000h
	 mov eax, 055555555h
         rep stosd

But of course, it need to be cut in 2 "rep stosb" if the @ is not aligned to a 16 byte bloc
 
For the logic with a maximum size of 65536 bytes you can recognize that you'll only ever cross at most one segment boundary where you need to change ES. So you can split your code into two steps, one before the segment needs changing and one after. That way you don't need to do any calculations within the loop or rep'd instruction. Just a pre-calculation to find the value when the wrap would occur.

If you can line up your original address so that it's on a 16-byte boundary, then you can instead normalize the pointer by computing a new segment such that es:bx becomes new_es:0 (es + bx >> 4 : 0)
 
same with DMA too... transfer up to the boundary then another transfer after that.
 
Well, sort of--DMA boundaries don't necessarily correspond to segment boundaries. The rule is that an ISA DMA transfer must not cross a 64K (8 bit) or 128K (16 bit) physical address boundary, which really doesn't have anything to do with segment registers. This applies only to DMA that uses the 8237 DMA controller, which is really a support chip out of the 8085 world. PCI DMA is a whole different smoke--it's essentially a device acting as a busmaster setup, with device-dependent maximum payload size. Things get really interesting when more than 4GB of memory is installed.
 
Last edited:
Back
Top