#[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/