The opposite of function 0Ch: it returns in AL the colour of the pixel at column CX, row DX of page BH, decoding the mode's memory layout. In the 16-colour EGA and VGA modes that means reading all four bit planes and putting the bits together, which is awkward to do by hand.
Typical uses are flood fill, collision tests in simple games ("is the pixel ahead not black?") and saving a small area before drawing over it. Like 0Ch it costs one interrupt per pixel. Here a pixel is drawn and read back, together with its untouched neighbour:
MOV AX, 0013h ; 320x200, 256 colours: all pixels 0INT 10hMOV AX, 0C0Eh ; write a pixel, colour 0Eh (yellow)MOV BH, 0MOV CX, 10 ; xMOV DX, 10 ; yINT 10hMOV AH, 0Dh ; read it backMOV BH, 0MOV CX, 10MOV DX, 10INT 10h ; AL = its colourMOV [PIX1], ALMOV AH, 0Dh ; and its neighbour, never drawnMOV BH, 0MOV CX, 11MOV DX, 10INT 10hMOV [PIX2], ALMOV CX, 001Eh ; wait 2 s: CX:DX = 1E8480h microsecondsMOV DX, 8480hMOV AH, 86h ; BIOS: waitINT 15hMOV AX, 0003h ; mode 03h again: 80x25 text, clears the screenINT 10hMOV AH, 09hMOV DX, OFFSET TXT1INT 21hMOV AL, [PIX1]CALL PHEX2MOV AH, 09hMOV DX, OFFSET TXT2INT 21hMOV AL, [PIX2]CALL PHEX2MOV AH, 09hMOV DX, OFFSET TXT3INT 21hPIX1 DB 0PIX2 DB 0TXT1 DB "pixel 10,10 = $"TXT2 DB "h, pixel 11,10 = $"TXT3 DB "h", 13, 10, "$"PHEX2: ; print AL as two hex digits; changes AX, CX, DXPUSH AXMOV CL, 4SHR AL, CL ; the high nibble firstCALL PDIG1POP AXAND AL, 0Fh ; then the low one, falling into PDIG1PDIG1:ADD AL, "0"CMP AL, "9"JBE PDIG2ADD AL, 7 ; "A".."F"PDIG2:MOV DL, ALMOV AH, 02h ; DOS: print DLINT 21hRET
Pitfalls
In text modes the result means nothing. In the CGA modes some BIOSes return the colour with the XOR bit or other high bits undefined, so AND AL, 3 (or AND AL, 0Fh in 16-colour modes) is a safe habit. To read a whole area, go to video memory: in mode 13h a byte per pixel; in the planar modes select each plane in turn with the graphics controller's Read Map Select register (index 4 at port 3CEh) and read it.