#[1]nesdoug » Feed [2]nesdoug » Comments Feed [3]nesdoug » 65816 Basics
Comments Feed [4]SNES Overview [5]alternate [6]alternate [7]nesdoug
[8]WordPress.com
[9]Skip to content
[10]nesdoug
NES Programming with cc65
65816 Basics
Programming the SNES in assembly, using the ca65 assembler.
Assembly Language Basics
When computer code is compiled, in a higher level language, it is
converted to a binary code (machine code) that the CPU can read and
run. Binary code is very hard to read and write. So, they developed a
system of mnemonics to make it easier to understand, called assembly
language.
There are many different assembly languages, each targeting a specific
CPU. We are targeting the 65816 (65c816) which is a more advanced
version of the popular 6502 chip. The best way to learn 65816 assembly
is to first learn 6502. But first, lets review the basics.
.
Number Systems
Binary. Under the hood, all computers process binary numbers. A series
of 1s and 0s. In the binary system, each column is 2x the value of the
number to the right.
0001 = 1
0010 = 2
0100 = 4
1000 = 8
You then add all the 1’s up
0011 = 2+1 = 3
0101 = 4+1 = 5
0111 = 4+2+1 = 7
1111 = 8+4+2+1 = 15
Each of these digits is called a bit. Typically, there are 8 bits in a
byte. So you can have numbers from
0000 0000 = 0
to
1111 1111 = 255
Since it is difficult to read binary, we will use hexadecimal instead.
Hexadecimal is a base 16 numbering system. Every digit is 16x the
number to the right. We use the normal numbers from 0-9 and then
letters A-F for the values 10,11,12,13,14,15. In many assembly
languages, we use $ to indicate hex numbers.
$0 = 0
$1 = 1
$2 = 2
$3 = 3
$4 = 4
$5 = 5
$6 = 6
$7 = 7
$8 = 8
$9 = 9
$A = 10
$B = 11
$C = 12
$D = 13
$E = 14
$F = 15
$F is the same as binary 1111.
The next column of numbers is multiples of 16.
$00 = 16*0 = 0 _____ $80 = 16*8 = 128
$10 = 16*1 = 16 _____ $90 = 16*9 = 144
$20 = 16*2 = 32 ____ $A0 = 16*10 = 160
$30 = 16*3 = 48 ____ $B0 = 16*11 = 176
$40 = 16*4 = 64 ____ $C0 = 16*12 = 192
$50 = 16*5 = 80 ____ $D0 = 16*13 = 208
$60 = 16*6 = 96 ____ $E0 = 16*14 = 224
$70 = 16*7 = 112 ____ $F0 = 16*15 = 240
$F0 is the same as binary 1111 0000.
add that to $0F (0000 1111) to get
$FF = 1111 1111
So you see, you can represent 8 bit binary numbers with 2 hex digits.
From $00 to $FF (0 – 255).
To get the assembler to output the value 100 you could write…
.byte 100
or
.byte $64
.
16 bit numbers
Typically (on retro systems) you use 16 bit numbers for memory
addresses. Memory addresses are locations where pieces of information
can be stored and read later. So, you could write a byte of data to
address $1000, and later read from $1000 to get that data.
The registers on the SNES can be set to either 8 bit or 16 bit modes.
16 bit mode means it can move information 16 bits at a time, and
process the information 16 bits at a time. 16 bit registers means that
it will read a byte from an address, and another from the address+1.
Same with writing 16 bits. It will write (low order byte) to the
address and (high order byte) to address+1.
In binary, a 16 bit value can go from
0000 0000 0000 0000 = 0
to
1111 1111 1111 1111 = 65535
In hex values, that’s $0000 to $FFFF.
Let’s say we have the value $1234. The 12 is the most significant byte
(MSB), and the 34 is the least significant byte (LSB). To calculate
it’s value by hand we can multiply each column by multiples of 16.
$1234
4 x 1 = 4
3 x 16 = 48
2 x 256 = 512
1 x 4096 = 4096
4096 + 512 + 48 + 4 = 4660
To output a 16 bit value $ABCD, you could write
.word $ABCD
(outputs $cd then $ab, little endian style)
Don’t forget the $.
We can also get the upper byte or lower byte of a 16 bit value using
the < and > symbols before the value.
Let’s say label List2 is at address $1234
.byte >List2
will output a $12 (the MSB)
.byte <List2
will output a $34 (the LSB).
.
24 bit numbers
We can now access addresses beyond $ffff. There is a byte above that
called the “bank byte”. Using long 24 bit addressing modes or changing
the data bank register, we can access values in that bank using regular
16 bit addressing. Here is an example of a 24 bit operation.
LDA f:$7F0000
will read a byte from address $0000 of the $7F bank (part of the WRAM).
In ca65, the f: is to force 24 bit values from the symbol / label. The
assembler will calculate the correct values. (to force 16 bit you use
a: and to force 8 bit you use z:)
JMP $018000
will jump to address $8000 in bank $01.
To output a 24 bit value
.faraddr $123456
(outputs $56…$34…$12)
Or you could do this, to output a byte at a time.
.byte ^$123456
(outputs $12)
.byte >$123456
(outputs $34)
.byte <$123456
(outputs $56)
But we don’t want to write our program entirely using byte statements.
That would be crazy. We will use assembly language, and the assembler
will convert our three letter mnemonics into bytes for us.
LDA #$12
(load the A register with the value $12)
will be converted by the assembler into this machine code that the
65816 CPU can execute…
$A9 $12
.
65816 CPU Details
There are 3 registers to work with
A (the accumulator) for most calculations and purposes
X and Y (index registers) for accessing arrays and counting loops.
A,X, and Y can be set to either 8 bit or 16 bit. The accumulator is
sometimes called C when it is in 16 bit mode. Setting the Accumulator
to 8 bit does not destroy the upper byte, you can access it with XBA
(swap high and low bytes). However, setting the Index registers to 8
bit will delete the upper bytes of X and Y.
There is a 16-bit stack pointer (SP or S) for the hardware stack. If
you call a function (subroutine) it will store the return address on
the stack, and when the function ends, it will pop the return address
back to continue the main program. The stack always exists on bank zero
(00).
Processor Status Flags (P), to determine if a value is negative, zero,
greater/lesser/equal to, etc. Used to control the flow of the program,
like if/then statements. Also the register size (8 bit or 16 bit) are
set/reset as status flags. *(see below)
There is a 16-bit direct page (DP) register, which is like the zero
page on the 6502 system, except that it is now movable. Typically,
people leave it set to $0000 so that it works the same as the 6502.
Zero page is a way to reduce ROM size, by only using 1 byte to refer to
an address. The DP always exists on bank zero (00).
The Program Bank Register (PBR or K) is the bank byte (highest byte) of
the 24 bit address of where the program is running. Together, with the
program counter (PC) the CPU will execute the program at this location.
The PBR does NOT increment when the PC overflows from FFFF to 0000, so
you can’t have code that flows from one bank to another. You can’t
directly set the PBR, but jumping long will change it, and you can push
it to the stack to be used by the…
Data Bank Register (DBR or B) is the bank byte (highest byte) of the 24
bit address of where absolute addressing (16 bit) reads and writes.
Usually you want to set it to the same as where your program is
running. You do it with this…
PHK (push program bank to stack)
PLB (pull from stack to data bank)
But you can also set it to another bank, to use absolute addressing to
access that bank’s addresses.
There is also a hidden switch to change the processor from Native Mode
(all 65816 instructions) to Emulation Mode (only 6502 instructions,
minus bugs and minus unofficial opcodes). The CPU powers on in
Emulation Mode, so you will usually see
CLC (clear the carry flag)
XCE (transfer carry flag to CPU mode)
near the start, to put it in Native Mode.
.
Status Flags
NVMXDIZC
– – – B – – – – (emulation mode only)
N negative flag, set if an operation sets the highest bit of a register
V overflow flag, for signed math operations
M Accumulator size, set for 8-bit, zero for 16-bit
X Index register size, set for 8-bit, zero for 16-bit
D decimal flag, for decimal (instead of hexadecimal) math
I IRQ disable flag, set to block IRQ interrupts
Z zero flag, set if an operation sets a register to zero
. . . . or if a comparison is equal
C carry flag, for addition/subtraction overflow
B break flag, if software break BRK used.
.
Where does the program start? It always boots in bank zero, in
emulation mode, and pulls an address (vector) off the Emulation Mode
Reset Vector located at $00FFFC and $00FFFD, then jumps to that address
(always jumping to bank zero). Your program should set it to Native
Mode, after which these are the important vectors.
IRQ $00FFEE-00FFEF (interrupt vector)
NMI $00FFEA-00FFEB (non-maskable interrupt vector)
If an interrupt happens, it will jump to the address located here
(always jumping to bank zero).
There is no Reset Vector in Native Mode. Hitting reset will
automatically put it back into Emulation Mode, and it will use that
Reset Vector.
But more on those later.
I highly recommend you learn more about 6502 assembly before
continuing. Here are some links that are helpful.
[11]
http://www.6502.org/tutorials/6502opcodes.html
[12]
https://skilldrick.github.io/easy6502/
[13]
https://archive.org/details/6502_Assembly_Language_Programming_by_L
ance_Leventhal/mode/1up
and 65816 assembly reference here.
[14]
https://wiki.superfamicom.org/65816-reference
and for the very bold, the really really big detailed book on the
subject.
[15]
http://archive.6502.org/datasheets/wdc_65816_programming_manual.pdf
Share this:
* [16]Twitter
* [17]Facebook
*
Like this:
Like Loading...
[18]April 3, 2020April 4, 2020 [19]dougfraker
Leave a Reply [20]Cancel reply
Enter your comment here...
____________________________________________________________
____________________________________________________________
____________________________________________________________
____________________________________________________________
Fill in your details below or click an icon to log in:
*
*
*
*
[21]Gravatar
Email (required) (Address never made public)
____________________
Name (required)
____________________
Website
____________________
WordPress.com Logo
You are commenting using your WordPress.com account. ( [22]Log Out /
[23]Change )
Google photo
You are commenting using your Google account. ( [24]Log Out /
[25]Change )
Twitter picture
You are commenting using your Twitter account. ( [26]Log Out /
[27]Change )
Facebook photo
You are commenting using your Facebook account. ( [28]Log Out /
[29]Change )
[30]Cancel
Connecting to %s
[ ] Notify me of new comments via email.
[ ] Notify me of new posts via email.
Post Comment
Post navigation
[31]Previous Previous post: SNES Overview
Search for: ____________________ Search
Recent Posts
* [32]65816 Basics
* [33]SNES Overview
* [34]SNES Projects
* [35]24. Advanced Mapper – MMC3
* [36]Review – 150 Classic NES Games for GBA
Recent Comments
Marcus on [37]24. Advanced Mapper –…
[38]dougfraker on [39]23. Advanced mapper MMC1
[40]dougfraker on [41]23. Advanced mapper MMC1
Aeris on [42]23. Advanced mapper MMC1
Aeris on [43]23. Advanced mapper MMC1
Archives
* [44]April 2020
* [45]March 2020
* [46]November 2019
* [47]October 2019
* [48]September 2019
* [49]April 2019
* [50]September 2018
* [51]July 2018
* [52]June 2018
* [53]March 2018
* [54]October 2017
* [55]September 2017
* [56]April 2017
* [57]March 2016
* [58]January 2016
* [59]December 2015
Categories
* [60]Uncategorized
Meta
* [61]Register
* [62]Log in
* [63]Entries feed
* [64]Comments feed
* [65]WordPress.com
[66]Blog at WordPress.com.
Close and accept Privacy & Cookies: This site uses cookies. By
continuing to use this website, you agree to their use.
To find out more, including how to control cookies, see here:
[67]Cookie Policy
IFRAME: [68]likes-master
%d bloggers like this:
References
Visible links
1.
https://nesdoug.com/feed/
2.
https://nesdoug.com/comments/feed/
3.
https://nesdoug.com/2020/04/03/65816-basics/feed/
4.
https://nesdoug.com/2020/04/02/snes-overview/
5.
https://public-api.wordpress.com/oembed/?format=json&url=
https://nesdoug.com/2020/04/03/65816-basics/&for=wpcom-auto-discovery
6.
https://public-api.wordpress.com/oembed/?format=xml&url=
https://nesdoug.com/2020/04/03/65816-basics/&for=wpcom-auto-discovery
7.
https://nesdoug.com/osd.xml
8.
https://s1.wp.com/opensearch.xml
9.
https://nesdoug.com/2020/04/03/65816-basics/#content
10.
https://nesdoug.com/
11.
http://www.6502.org/tutorials/6502opcodes.html
12.
https://skilldrick.github.io/easy6502/
13.
https://archive.org/details/6502_Assembly_Language_Programming_by_Lance_Leventhal/mode/1up
14.
https://wiki.superfamicom.org/65816-reference
15.
http://archive.6502.org/datasheets/wdc_65816_programming_manual.pdf
16.
https://nesdoug.com/2020/04/03/65816-basics/?share=twitter
17.
https://nesdoug.com/2020/04/03/65816-basics/?share=facebook
18.
https://nesdoug.com/2020/04/03/65816-basics/
19.
https://nesdoug.com/author/dougfraker/
20.
https://nesdoug.com/2020/04/03/65816-basics/#respond
21.
https://gravatar.com/site/signup/
22. javascript:HighlanderComments.doExternalLogout( 'wordpress' );
23.
https://nesdoug.com/2020/04/03/65816-basics/
24. javascript:HighlanderComments.doExternalLogout( 'googleplus' );
25.
https://nesdoug.com/2020/04/03/65816-basics/
26. javascript:HighlanderComments.doExternalLogout( 'twitter' );
27.
https://nesdoug.com/2020/04/03/65816-basics/
28. javascript:HighlanderComments.doExternalLogout( 'facebook' );
29.
https://nesdoug.com/2020/04/03/65816-basics/
30. javascript:HighlanderComments.cancelExternalWindow();
31.
https://nesdoug.com/2020/04/02/snes-overview/
32.
https://nesdoug.com/2020/04/03/65816-basics/
33.
https://nesdoug.com/2020/04/02/snes-overview/
34.
https://nesdoug.com/2020/03/19/snes-projects/
35.
https://nesdoug.com/2019/11/11/23-advanced-mapper-mmc3/
36.
https://nesdoug.com/2019/10/31/review-150-classic-nes-games-for-gba/
37.
https://nesdoug.com/2019/11/11/23-advanced-mapper-mmc3/comment-page-1/#comment-12577
38.
https://nesdoug.wordpress.com/
39.
https://nesdoug.com/2019/10/02/22-advanced-mapper-mmc1/comment-page-1/#comment-12081
40.
https://nesdoug.wordpress.com/
41.
https://nesdoug.com/2019/10/02/22-advanced-mapper-mmc1/comment-page-1/#comment-12080
42.
https://nesdoug.com/2019/10/02/22-advanced-mapper-mmc1/comment-page-1/#comment-12077
43.
https://nesdoug.com/2019/10/02/22-advanced-mapper-mmc1/comment-page-1/#comment-12076
44.
https://nesdoug.com/2020/04/
45.
https://nesdoug.com/2020/03/
46.
https://nesdoug.com/2019/11/
47.
https://nesdoug.com/2019/10/
48.
https://nesdoug.com/2019/09/
49.
https://nesdoug.com/2019/04/
50.
https://nesdoug.com/2018/09/
51.
https://nesdoug.com/2018/07/
52.
https://nesdoug.com/2018/06/
53.
https://nesdoug.com/2018/03/
54.
https://nesdoug.com/2017/10/
55.
https://nesdoug.com/2017/09/
56.
https://nesdoug.com/2017/04/
57.
https://nesdoug.com/2016/03/
58.
https://nesdoug.com/2016/01/
59.
https://nesdoug.com/2015/12/
60.
https://nesdoug.com/category/uncategorized/
61.
https://wordpress.com/start?ref=wplogin
62.
https://nesdoug.wordpress.com/wp-login.php
63.
https://nesdoug.com/feed/
64.
https://nesdoug.com/comments/feed/
65.
https://wordpress.com/
66.
https://wordpress.com/?ref=footer_blog
67.
https://automattic.com/cookies
68.
https://widgets.wp.com/likes/master.html?ver=20190321#ver=20190321
Hidden links:
70.
https://nesdoug.com/2020/04/03/65816-basics/#comment-form-guest
71.
https://nesdoug.com/2020/04/03/65816-basics/#comment-form-load-service:WordPress.com
72.
https://nesdoug.com/2020/04/03/65816-basics/#comment-form-load-service:Twitter
73.
https://nesdoug.com/2020/04/03/65816-basics/#comment-form-load-service:Facebook
74.
https://nesdoug.wordpress.com/
75.
https://nesdoug.wordpress.com/