Mystery solved, I think. On my XP systems, without first executing a CLS the direct memory writes, and probably also the reads, do not work. After executing a CLS they both work. This would appear to be a security measure.
.model small,c
.386
.stack
.data
.code
;----------------------------------------------------------------------------
; Calls the BIOS Set Cursor Position function to set the cursor position for
; display page 0 to <row>,<col> (upper left corner is position 0,0).
;----------------------------------------------------------------------------
locate proc uses eax ebx edx row:BYTE, col:BYTE
mov ah, 2
mov bh, 0
mov dh, row
mov dl, col
int 10h
ret
locate endp
;----------------------------------------------------------------------------
; Clears the screen by calling the BIOS Scroll Current Page Up function with
; a scroll (row) count of zero, and sets the cursor position to the upper
; left corner of the screen. An 80x25 alphanumeric mode screen is assumed.
;----------------------------------------------------------------------------
cls proc uses eax ebx ecx edx
mov ah, 6
mov al, 0
mov bh, 7
mov ch, 0
mov cl, 0
mov dh, 24
mov dl, 79
int 10h
invoke locate, 0, 0
ret
cls endp
.startup
push 0b800h
pop es
mov BYTE PTR es:[0], 'X'
mov BYTE PTR es:[2], 'Y'
mov BYTE PTR es:[4], 'Z'
mov al, es:[0]
mov es:[6], al
xor ah, ah
int 16h
invoke cls
push 0b800h
pop es
mov BYTE PTR es:[8], 'X'
mov BYTE PTR es:[10], 'Y'
mov BYTE PTR es:[12], 'Z'
mov al, es:[8]
mov es:[14], al
xor ah, ah
int 16h
.exit
end