How to move data around
Load instruction : ld
LD
Load - moving data between memory and CPU
e.g. ld a, 30 => a = 30
LDH
Load High - moving data between HRAM memory and CPU.
Takes fewer cycles and bytes than ld. the 0xFF high byte is implied.
Can indirect through [c] for even more savings
What is special about the c register?
Can use it for indirection when using LDH
JP
Jump to address.
No built-in indirection for the address (can do the stack tricks with RET)
Can use the conditional form
JR
Jump Relative - jump +127 / -128 bytes from current location.
Save a cycle and a byte _(maybe more?)_
Prefer JR untill the assembler gripes at you
can use the conditional form
CALL
Jump to subroutine.
Pushes next address to execute on the stack pointed to by SP
Condition flags
Z : zero flag is set
NZ: zero flag clear
C : carry flag is set
CZ: carry flag clear
RET
Return from subroutine - pops address off the stack
RETI
Return from subroutine and enable interrupts
RST
Jump through Restart Vector
How many restart vectors are there, and what are their addresses?
8 vectors, with 8 bytes available for eacah
$10 $18
$20 $28
$30 $38
$40 $48
Save two bytes / two cycles by jumping through these.
One byte operand, 0x00 is prepended to it.
ADC
Add with carry
ADD
Add without carry
DEC
Decrement operand
INC
Increment operand
CP
compare with accumulator - Acc - operand, and set Z and C flags
SBC
Subtract with carry
SUB
Subtract without carry
AND
bitwise AND of accumulator with operand
OR
bitwise OR of accumulator with operand
XOR
bitwise XOR of accumulator with operand.
Use XOR a to zero accumulator and clear carry flag
How to clear carry flag
xor a
(there is no specific instruction)
BIT
Test a bit in the operand. Sets Z to 1 if it is clear (so sets z to the NOT of the tested bit…)
RES
Reset (clear) a speciifc bit in the operand
SET
Set a specific bit in the operand
SWAP
exchange the nybbles of a byte
RL / RLA
Roll left / Roll left accumulator (short form instruction)
Roll into carry, carry put into bit zero
RLC / RLCA
Rotate Left CIRCULAR / Rotate Left Curcular accumulator (short form instruction)
NOT carry
The carry bit is set, but never used.
RR / RRA
Rotate Right / Rotate Right accumulator (short form instruction)
Carry is involved in the bits
RRC / RRCA
Rotate Right CIRCULAR / Rotate Right Circular accumulator (short form instruction)
(not Carry)
Carry is set from the rotation, but does not contribute.
SLA
Shift Left Arithmetic (not accumulator-specific)
Zero shifted in, high bit goes to carry
SRA
Shift Right Arthimetic (not accumulator-specific)
High bit duplicated, bit zero goes into carry
SRL
Shift RIght Logical
Zero shifted in, bit zero goes into carry
POP
Take 16 bits from SP and putting into the operand. Updates SP
PUSH
Move 16 bits from operand onto the stack. Updates SP
Push Down Stack
GB’s SP style. Starts at high memory and fills down. Lower addresses are newer values on the stack.
CCF
Complement Carry Flag
(there is no clear carry flag instruction)
SCF
Set carry flag
CPL
Complement accumulator
DAA
Convert value to BCD
DI
Disable Interrupts
EI
Enable Interrupts
NOP
NOP!
HALT
Go to low-power state
STOP
Go to very low power state.
DO NOT USE (unless you’re doing CGB games), it can damage the screen
How can STOP destroy the screen?
If the stop happens during a screen update (which is trickling voltage to the screen), then the voltage never stops, eventually causing a permanent black line as the LCD cells get burned out.
T-States
Tick states. There are four ticks for each machine cycle
M-Cycles
Machine cycles - four ticks each. Instructions execute in complete machine cycles, and is a more convenient metric for cost of instructions
Each instruction is 1-6 machine cycles
GameBoy Processor
Sharp LR35902 - 4.19 mhz T-States, 1.049 M-Cycles
Flags
Z - Zero
C - Carry
(BCD flags, not really used)
N - Negative
H - Half-carry from nybble to nybble
[operand]
Indirection syntax
registers
af - accumulator + flags
bc - generic 8/16. C used in LDH indirection
de - generic 8/16
hl - generic 8/16. Primary indirection register (High / Low)
sp
pc
IME
Interrupt Master Enable
HLI / HLD
when indirect, [HLI] will use HL, but increment after use
[HLD] will use HL. but increment after use
Other syntaxes:
[HL+] [HL-] // I like this one
LDI / LDD as pseudo instructions
Interrupt Vectors
There are five interrupt vectors
$40 - VBlank
$48 - LCD Status
$50 - TImer overflow
$58 - serial transfer completion
$60 - joypad transition
Macro syntax
macro name
ld high(\1), high(\2)
ld low(\1), low(\2)
jr nz oop_ack\@
…
oop_ack\@:
endm
Constant syntax
def OOP_ACK equ $1234
def BORK equ (5+7)
Two kinds of labels
global labels:
label: …
local labels:
.label: …
Local labels only have to be unique in regions bounded by global labels
section syntax
section “name”, rom0[$1000]
Name is just used to connect sections. does not survive to ROM
the [$1000] is start address, and is optinal. otherwise the toolcahin will pick a space
Can use FRAGMENT for cross-source-file sections
rom0 is the type (There are other types, TBD), and the zero is the bani (details TBD)
a = a+b;
if (a != 0) { …something… }
add a,b
jp z, zero
…something…
zero:
a = a+ b;
if (a == 0) { …something-1 }
else { …something-2 }
jp nz, not_zero
something-1
jp zero__check_end
not_zero:
something-2
zero__check_end:
c = 8;
while (c != 0) {
…something
c—;
}
ld c,8
loop:
something
dec c
jp nz, noop
Zuletzt geändertvor einem Tag