as: i386-16bit

 
 9.15.14 Writing 16-bit Code
 ---------------------------
 
 While 'as' normally writes only "pure" 32-bit i386 code or 64-bit x86-64
 code depending on the default configuration, it also supports writing
 code to run in real mode or in 16-bit protected mode code segments.  To
 do this, put a '.code16' or '.code16gcc' directive before the assembly
 language instructions to be run in 16-bit mode.  You can switch 'as' to
 writing 32-bit code with the '.code32' directive or 64-bit code with the
 '.code64' directive.
 
    '.code16gcc' provides experimental support for generating 16-bit code
 from gcc, and differs from '.code16' in that 'call', 'ret', 'enter',
 'leave', 'push', 'pop', 'pusha', 'popa', 'pushf', and 'popf'
 instructions default to 32-bit size.  This is so that the stack pointer
 is manipulated in the same way over function calls, allowing access to
 function parameters at the same stack offsets as in 32-bit mode.
 '.code16gcc' also automatically adds address size prefixes where
 necessary to use the 32-bit addressing modes that gcc generates.
 
    The code which 'as' generates in 16-bit mode will not necessarily run
 on a 16-bit pre-80386 processor.  To write code that runs on such a
 processor, you must refrain from using _any_ 32-bit constructs which
 require 'as' to output address or operand size prefixes.
 
    Note that writing 16-bit code instructions by explicitly specifying a
 prefix or an instruction mnemonic suffix within a 32-bit code section
 generates different machine instructions than those generated for a
 16-bit code segment.  In a 32-bit code section, the following code
 generates the machine opcode bytes '66 6a 04', which pushes the value
 '4' onto the stack, decrementing '%esp' by 2.
 
              pushw $4
 
    The same code in a 16-bit code section would generate the machine
 opcode bytes '6a 04' (i.e., without the operand size prefix), which is
 correct since the processor default operand size is assumed to be 16
 bits in a 16-bit code section.