9.2. Addressing Between Different-Size Segments
===============================================
If your OS is mixed 16 and 32-bit, or if you are writing a DOS
extender, you are likely to have to deal with some 16-bit segments and
some 32-bit ones. At some point, you will probably end up writing code
in a 16-bit segment which has to access data in a 32-bit segment, or
vice versa.
If the data you are trying to access in a 32-bit segment lies within
the first 64K of the segment, you may be able to get away with using an
ordinary 16-bit addressing operation for the purpose; but sooner or
later, you will want to do 32-bit addressing from 16-bit mode.
The easiest way to do this is to make sure you use a register for the
address, since any effective address containing a 32-bit register is
forced to be a 32-bit address. So you can do
mov eax,offset_into_32_bit_segment_specified_by_fs
mov dword [fs:eax],0x11223344
This is fine, but slightly cumbersome (since it wastes an
instruction and a register) if you already know the precise offset you
are aiming at. The x86 architecture does allow 32-bit effective
addresses to specify nothing but a 4-byte offset, so why shouldn't NASM
be able to generate the best instruction for the purpose?
It can. As in *Note Section 9.1::, you need only prefix the address
with the `DWORD' keyword, and it will be forced to be a 32-bit address:
mov dword [fs:dword my_offset],0x11223344
Also as in *Note Section 9.1::, NASM is not fussy about whether the
`DWORD' prefix comes before or after the segment override, so arguably
a nicer-looking way to code the above instruction is
mov dword [dword fs:my_offset],0x11223344
Don't confuse the `DWORD' prefix _outside_ the square brackets,
which controls the size of the data stored at the address, with the one
`inside' the square brackets which controls the length of the address
itself. The two can quite easily be different:
mov word [dword 0x12345678],0x9ABC
This moves 16 bits of data to an address specified by a 32-bit
offset.
You can also specify `WORD' or `DWORD' prefixes along with the `FAR'
prefix to indirect far jumps or calls. For example:
call dword far [fs:word 0x4321]
This instruction contains an address specified by a 16-bit offset;
it loads a 48-bit far pointer from that (16-bit segment and 32-bit
offset), and calls that address.