Output · Screen
The screen: drawing is writing memory
Hack has no draw instruction and no graphics card. The screen is a particular block of memory — write 0s and 1s into the 8K words starting at 16384 and the pixels follow. This page shows how that memory maps onto pixels, and how to write it.
01Where the screen lives: RAM 16384–24575
The first 16K of RAM is ordinary data (variables, stack); the next 8K words are the screen:
| Address | What it is | Size |
|---|---|---|
| 0 – 16383 | data | 16K words |
| 16384 – 24575 | screen | 8192 words |
| 24576 | keyboard | 1 word |
So @SCREEN in assembly is just @16384 — a predefined symbol, not a new instruction.
02One bit = one pixel
The screen is 512 × 256 black-and-white pixels. One 16-bit word lights 16 consecutive pixels:
Do the arithmetic: 512 ÷ 16 = 32 words per row; 256 rows × 32 = 8192 words, exactly the block above.
03The address formula
Row r, word c (c from 0 to 31):
address = 16384 + 32 × r + c
and bit b of that word (b from 0 to 15, bit 0 leftmost) is pixel column c × 16 + b.
The order is reversed: written as a number bit 15 is leftmost, but on screen the leftmost pixel is bit 0. Writing 0x0001 lights the leftmost pixel of the row; 0x8000 lights the rightmost.
| What you want to draw | How |
|---|---|
| a row | compute the address of its first word, then write 32 words |
| one pixel | read that word, set one bit, write it back |
| the whole screen | write 8192 words starting at 16384 |
There is no shortcut around read-modify-write: to set a bit you do D=M, D=D|mask, then M=D.
04Hands-on: click cells and watch the words change
Below is a 32 × 16 mini screen. Each row of 32 pixels is 2 words. Click any cell and the two words’ binary and addresses update on the right. Click the leftmost pixel and the last bit of the binary flips to 1.
Click a cell = write one bit
The demo is only 32 pixels wide (a real row is 512 pixels = 32 words). Click and watch the words below change.
The matching words
| Row | Left word (16 bits) | Address | Right word (16 bits) | Address |
|---|---|---|---|---|
| 4 | 0000111111110000 | 16512 | 0000000000000000 | 16513 |
| 5 | 0000100000010000 | 16544 | 0000000000000000 | 16545 |
| 6 | 0000100000010000 | 16576 | 0000000000000000 | 16577 |
| 7 | 0000100000010000 | 16608 | 0000000000000000 | 16609 |
| 8 | 0000100000010000 | 16640 | 0000000000000000 | 16641 |
| 9 | 0000100000010000 | 16672 | 0000000000000000 | 16673 |
| 10 | 0000100000010000 | 16704 | 0000000000000000 | 16705 |
| 11 | 0000111111110000 | 16736 | 0000000000000000 | 16737 |
05Three useful assembly snippets
Clear the screen: write 0 into all 8192 words.
@SCREEN D=A @i M=D (LOOP) @i D=M @24576 D=D-A // stop once we reach 24576 @END D;JEQ @i A=M M=0 // clear the current word @i M=M+1 @LOOP 0;JMP (END) @END 0;JMP
Fill one row: write -1 into all 32 words of a row (all 16 bits set).
The 16-bit form of -1 is all ones, so one M=-1 lights 16 pixels — a row takes only 32 writes.
Draw one pixel: compute the word address and the mask, then read-modify-write.
// draw pixel (x, y): // addr = 16384 + 32*y + (x / 16) // mask = 1 << (x % 16) <- bit 0 is leftmost // Hack has no multiply, divide or shift: // 32*y, x/16 and x%16 must all be computed with loops (assumed done here) @addr A=M D=M // read the word's current 16 pixels @mask // only the bit to light is 1 in mask D=D|M // set that bit, leave the rest @addr A=M M=D // write it back to the screen
06Why design it this way
Making the screen ordinary memory means the CPU never needs to know a screen exists: it writes an address, and the hardware (address decoding inside Memory) turns the write into pixels.
| Approach | Price |
|---|---|
| Memory mapping (what Hack does) | drawing is writing memory; the CPU stays simple, but it costs 8K of address space |
| Dedicated display instructions | the CPU needs extra control logic and opcodes |
| A separate graphics card | another processor and its own memory — not in this course |
The price is real too: a frame is 8K words, thousands of instructions word by word, which is why animation on Hack stays modest.