Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/assets/hello-world.asm
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ EntryPoint:
WaitVBlank:
ld a, [rLY]
cp 144
jp c, WaitVBlank
jr c, WaitVBlank

; Turn the LCD off
ld a, 0
Expand All @@ -39,7 +39,7 @@ CopyTiles:
dec bc
ld a, b
or a, c
jp nz, CopyTiles
jr nz, CopyTiles
; ANCHOR_END: memcpy

; Copy the tilemap
Expand All @@ -53,7 +53,7 @@ CopyTilemap:
dec bc
ld a, b
or a, c
jp nz, CopyTilemap
jr nz, CopyTilemap

; Turn the LCD on
ld a, LCDC_ON | LCDC_BG_ON
Expand All @@ -66,7 +66,7 @@ CopyTilemap:
; ANCHOR_END: bgp_write

Done:
jp Done
jr Done


SECTION "Tile data", ROM0
Expand Down
9 changes: 6 additions & 3 deletions src/part1/jumps.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ There are four of them:
| Call | `call` | Call a subroutine |
| Return | `ret` | Return from a subroutine |

We will focus on `jp` for now.
`jp`, such as the one line {{#line_no_of "^\s*jp" ../assets/hello-world.asm}}, simply sets PC to its argument, jumping execution there.
We will focus on the first two, `jp` and `jr`, for now.

`jp`, such as the one on line {{#line_no_of "^\s*jp" ../assets/hello-world.asm}}, simply sets PC to its argument, jumping execution there.
In other words, after executing `jp EntryPoint` (line {{#line_no_of "^\s*jp EntryPoint" ../assets/hello-world.asm}}), the next instruction executed is the one below `EntryPoint` (line <!-- should be {{#line_no_of "^\s*EntryPoint:" ../assets/hello-world.asm}} + 1 --> 11).

:::tip:🤔
Expand All @@ -38,6 +39,8 @@ Don't worry, we will see later why it's required.

:::

`jr`, such as the one on line {{#line_no_of "^\s*jr" ../assets/hello-world.asm}}, is functionally the same as `jp`. However, it sets PC *relative* to the current PC value, and can only jump execution forward or backward by 128 bytes---a short distance given that each instruction takes one to three bytes. The advantage of `jr` is that it takes up two bytes instead of three like `jp` (since it encodes a one-byte relative distance instead of a two-byte absolute address), and also takes one CPU cycle less than `jp` to execute, so it's commonly used when you know that a jump will be short.

## Conditional jumps

Now to the _really_ interesting part.
Expand Down Expand Up @@ -94,7 +97,7 @@ There are four "conditions":
| Carry | `c` | C is set (last operation overflowed) |
| No carry | `nc` | C is not set (last operation did not overflow) |

Thus, `jp nz, CopyTiles` can be read as "if the Z flag is not set, then jump to `CopyTiles`".
Thus, `jr nz, CopyTiles` can be read as "if the Z flag is not set, then jump to `CopyTiles`".
Since we're jumping _backwards_, we will repeat the instructions again: we have just created a **loop**!

Okay, we've been talking about the code a lot, and we have seen it run, but we haven't really seen _how_ it runs.
Expand Down