You can either allocate a static buffer in your executable or dynamically allocate a buffer like suggested by Micheal. To statically allocate a 64K buffer you want to do something like this:
BITMAPBUF SEGMENT PARA PRIVATE
DB 0ffffh DUP (?)
BITMAPBUF ENDS
BITMAPBUF2 SEGMENT BYTE PRIVATE
DB ?
BITMAPBUF2 ENDS
The BITMAPBUF2
segment is a bit of hack to get around the fact that the versions of TASM and TLINK I'm using don't seem to handle 64K segments correctly. So I create two segments that the linker will place adjacent to each other.
To allocate the buffer dynamically using MS-DOS you want code something like this:
mov ah, 48h
mov bx, 1000h
int 21h
jc failed
mov [bitmapbuf_seg], ax
Note that if you're trying to create a .COM file both of these methods will fail. The former because .COM files can't be greater than 64K and the second because .COM executables allocate all of free memory when they start(*), so there's no memory to dynamically allocate. You can solve the later problem by freeing unused memory before using INT 21h/AH=48h but the simpler solution is to build an .EXE instead.
Here some example code that copies the contents of the VGA frame buffer at A000:0000 to the buffer. Uncomment out one of the two lines at the start depeding whether the buffer was statically or dynamically allocated:
; mov ax, BITMAPBUF
; mov ax, [bitmapbuf_seg]
mov es, ax
xor di, di
mov ax, 0a000h
mov ds, ax
xor si, si
mov cx, 8000h
rep movsw
(*) actually it allocates the largest free contiguous block of memory, but that usually means pretty much all of conventional memory.