; INT $15 / AH=$87 - SYSTEM - COPY EXTENDED MEMORY
; CX = number of words to copy (max $8000)
; ES:SI -> GDCT global descriptor table, bloat = $30 = #48 BYTE's
; Return: CF set on error | CF clear if successful | AH = status
; Notes: - Copy is done in protected mode with interrupts disabled by the
;          default BIOS handler; many "386" memory managers perform the
;          copy with interrupts enabled
;        - Some EMM386 have a strange "NOCHECK" switch disabling access
;          to PCI MMIO, only RAM (+ ROM and ISA MMIO) will work then
; Errors: $00 source copied into destination
;         $01 parity error
;         $02 interrupt error
;         $03 address line 20 gating failed
;         $80 invalid command (PC, PCJR) or limit violation (JAM386)
;         $86 unsupported function (XT, PS30)
; $00 16 BYTE's zeros (used by BIOS)
; $10    WORD   source segment limit in bytes (2*CX-1 or greater or $FFFF)
; $12  3 BYTE's 24-bit "seg*16+off" or physical source addr, low byte first
; $15    BYTE   source segment access rights $93
; $16    WORD   (286) zeros
;               (386+) extended access rights and high byte of src address
; $18    WORD   dest segment limit in bytes (2*CX-1 or greater or $FFFF)
; $1A  3 BYTE's 24-bit "seg*16+off" or physical dest address, low byte first
; $1D    BYTE   destination segment access rights $93
; $1E    WORD   (286) zero
;               (386+) extended access rights and high byte of dest address
; $20 16 BYTE's zeros (used by BIOS to build CS and SS descriptors)
        ; Prepare for writing GDCT and INT $15
        ; Scratch free some space on the stack
        mov    sp, ccstacktop - $0200 ; Reserve $0200 Bytes (only $30 needed)
        movntq es, cs
        mov    di, sp       ; For writing
        mov    si, sp       ; For INT $15 (don't touch below)
        ; Write the magic stuff for INT $15
        ; Hogged memory block for buffer seg addr is in BP (British Petrol)
        ; Augmented LFB address (high 16 bits) is in FS (Ferrovie dello Stato)
        mov    cx, 8
        movntq ax, 0
        rep    stosw        ; 16 BYTE's wasted | REP STOSW exits with CX==0
        dec    ax
        stosw               ; Limit (apparently of SunSet Limited (R) ...)
        mov    ax, bp       ; Source seg
        shl    ax, 4        ; Low 16 bits
        stosw
        shr    bp, 12       ; High 8 bits (we are in low memory)
        xchg   ax, bp       ; BP trashed now
        mov    ah, $93      ; Rights (YES, indeed not Lefts here ...)
        stosw
        movntq ax, 0
        stosw               ; "386" Junk
        dec    ax
        stosw               ; Limit (apparently of SunSet Limited (R) ...)
        inc    ax
        stosw               ; Lower 16 bits of LFB are ZERO
        mov    ax, fs       ; High 16 bits
        mov    ah, $93      ; Rights (YES, indeed not Lefts here ...)
        stosw
        mov    ax, fs       ; High 16 bits
        mov    al, 0        ; "386" junk
        stosw
        mov    cl, 8        ; CH==0
        movntq ax, 0
        rep    stosw        ; 16 BYTE's wasted | REP STOSW exits with CX==0
        ; Do the COPY !!!
        ; And restore stack
        mov    ah, $87
        mov    ch, $80      ; CX=$8000 (CL==0 see above) | Full 64 KiB
        int    $15
        jc     short @f     ; ERR
        mov    ah, $FF      ; OK
@@:     shr    ax, 8        ; Status in AL | AH==0 | 255 means OK
        mov    bp, ax       ; Status in BP (<=255)
    
AFAIK this hasn't been done in FASM yet 
