Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- .-------------------------------------------------.
- ( P A R T 7 . S O M E A S S E M B L Y N O T E S )
- `-------------------------------------------------ยด
- general contents: pastebin.com/hmpJmurr
- This part is not meant to learn Assembly, only as a "reminder" of some things I tend to forget.
- o==========o
- | CONTENTS |
- o==========o
- A. Some mnemonics
- B. RAM locations
- C. Masking
- D. Self modifying code
- E. Error codes
- F. Writing under Kernal ROM bug
- G. Indirect indexed addressing
- Z. All opcodes
- Y. Tips
- X. References
- -<>-<>-<>-<>-<>-
- o===================o
- | A. Some mnemonics |
- o===================o
- Some that I tend to forget:
- ADC Add to accumulator
- BCS Greater or equal
- BCC Less (not equal)
- There's a complete list of mnemonics in appendix A from [1]: print it out.
- o==================o
- | B. RAM locations |
- o==================o
- Zero page:
- $05 & $06: Two bytes some use freely.
- $FB, $FC, $FD and $FE: Four bytes free to use for you.
- Interrupt:
- 0314 Hardware interupt vector, high byte (CINV, IRQ, default = $EA31)
- 0315 IRQ low byte
- Graphics (D000 and on):
- D020 Border color
- D021 Background color
- 0400 Screen RAM (char positions)
- Kernal (E000 and on):
- E544 Clear screen
- FFD2 Print char on screen (CHROUT)
- FFE4 Get keyboard input (GETIN)
- FFE1 Run/Stop
- o============o
- | C. Masking |
- o============o
- Set on with OR, set off with AND.
- a. Set a bit to 1 with OR 1 (use 0 to let through):
- 10010101 10100101 $95 $A5
- OR 11110000 11110000 $F0 $F0
- = 11110101 11110101 $F5 $F5
- b. Set a bit to 0 with AND 0 (use 1 to let through):
- 10100101 10100101
- AND 00001111 00001111
- = 00000101 00000101
- c. Toggle a bit with eXclusive OR 1 (use 0 to let through):
- 10011101 10010101
- XOR 00001111 11111111
- = 10010010 01101010
- d. Query the status of a bit. Use 1 and AND to check. Example: check status of bit 3 (fouth from the right):
- 10011101 10010101
- AND 00001000 00001000
- = 00001000 00000000
- e. BIT operation code. This is a tricky one. Mostly used for testing I/O from the CIA chips [4]. Example: if a joystick, or its fire button, is pressed then a bit in the register DC00_hex turns to zero. A BIT compare then may look like this:
- lda #%00000001 ;= #$01
- bit $dc00 ;Compare A with the value in $DC00
- bne .NotUpPressed
- jsr PlayerMoveUp
- If up is pressed on the joystick then bit zero of DC00_hex turns to 0. A logical AND is performed by BIT. The AND then returns a 0 for bit zero. Considering the fact that all of the other bits in the accumulator are 0 too the total value returned by the AND is 0. The BIT operation reverses that to 1 (i.e. the Z flag is set).
- The same can be done with "lda #$02", $04, $08 or $10 (even numbers) to check if down or left is pressed etc. (i.e. compare w/ bit 1 or 2, etc. of DC00_hex).
- Why use BIT and not AND? Because it does not change the value in the accumulator.
- The BIT operation also does two other things [2]. Bit 7 of the address that being compared to A is copied to the N (negative) flag/bit of the processor register (P). This is handy to test if a number in memory is negative (i.e. between -128 and +127) since the last bit determines the sign. Bit 6 gets copied the the V (overflow) flag so this bit can be checked with a BVS/BVS instruction.
- o========================o
- | D. Self modifying code |
- o========================o
- Example [3], change border and background color to white:
- border = $d020
- lda #<border
- sta modify+1
- lda #$01
- jsr modify
- inc modify+1
- jsr modify
- rts
- modify sta border
- rts
- o================o
- | E. Error codes |
- o================o
- If you use Kernal routines these are the error codes that are returned into the accumulator ([2], page 306):
- 0 Routine terminated by Stop key
- 1 Too many open files
- 2 File already open
- 3 File not open
- 4 File not found
- 5 Device not present
- 6 File is not an input file
- 7 File is not an output file
- 8 File name is missing
- 9 Illegal device number
- 1D_hex Load error
- 240 Top of memory change RS-232 buffer allocation/deallocation
- One might find some more error codes at: https://sta.c64.org/cbm64baserr.html and www.manualslib.com/manual/1517372/Commodore-Cbm-2040.html?page=88#manual. In [9] on page 241 some examples of what may cause these errors are given.
- o=================================o
- | F. Writing under Kernal ROM bug |
- o=================================o
- There appears to be a bug when you try to place data for the VIC under the shadow of the Kernal ROM (to place a custom character set there for instance). See: www.lemon64.com/forum/viewtopic.php?p=913323. The part of RAM from:
- FD30 to FD4F_hex
- gets accidentally overwritten by the Kernal even though the CPU cannot read from that part of RAM. This probably only happens when one presses the Restore key.
- o================================o
- | G. Indirect indexed addressing |
- o================================o
- Because the CPU is 8 bit but the addresses in RAM are 16 bit there is a "trick" to address a register via the CPU anyway. It's called "indirect addressing mode". It enables you to use two 8 bit values (2 bytes) at a time so you can perform operations with 16 bit addresses and mnemonics. You place one 8 bit value in parenthesis and the next one is also considered in your mnemonic.
- Syntax example:
- LDA ($FD),Y
- It loads the contents of $FD (with an offset of Y) into the accumulator and the contents of $FE in ... Well, you could think of it like it's loaded into the .X register. So it's as if the mnemonic says "load into .A contents of $FD and into .X the contents of $FD+1". However, the .X register appears to be still usable. Usually there are 16 bits "stored" somewhere in the processor because most addresses in RAM are 16 bit. If one loads a RAM address of only 8 bits in the CPU there is a "vacancy" of 8 bits somewhere. Maybe that's where the 8 bits that are the contents of $FE in the example are stored.
- Note: you can *ONLY* use a Zero Page address for this! So no LDA ($D000),Y.
- Example:
- ;Copy char ROM ($D000) to RAM underneath it
- lda #$d0 ;Load high byte of $D000
- sta $fc ;Store it in a free to use zero page location we use as vector
- ldy #$00 ;Init counter with 0
- sty $fb ;Store low byte (= 0) of $D000 in the $FB/$FC vector
- ;The contents of $FC/$FB is now: $D000
- lda ($fb),y ;Load .A and "imaginary .X" with the bytes that the vector stored
- ; in $fb/$fc points to (which is $00/$D0)
- sta ($fb),y ;Store contents of A and "X" to $D000 (i.e. under ROM at same position)
- rest of code (this needs to be done 256 times to include all characters)
- See: https://dustlayer.com/vic-ii/2013/4/23/vic-ii-for-beginners-part-2-to-have-or-to-not-have-character
- It looks like the four free to use Zero Page registers $FB, $FC, $FD and $FE are meant for this. Two for the (indexed) memory location from which you want to copy something, two for the destination.
- o================o
- | Z. All opcodes |
- o================o
- See [11].
- ADC add with carry LDA load accumulator
- AND and with accumulator LDX load X
- ASL arithmetic shift left LDY load Y
- BCC branch on carry clear LSR logical shift right
- BCS branch on carry set NOP no operation
- BEQ branch on equal (zero set) ORA or with accumulator
- BIT bit test PHA push accumulator
- BMI branch on minus (negative set) PHP push processor status (SR)
- BNE branch on not equal (zero clear) PLA pull accumulator
- BPL branch on plus (negative clear) PLP pull processor status (SR)
- BRK break / interrupt ROL rotate left
- BVC branch on overflow clear ROR rotate right
- BVS branch on overflow set RTI return from interrupt
- CLC clear carry RTS return from subroutine
- CLD clear decimal SBC subtract with carry
- CLI clear interrupt disable SEC set carry
- CLV clear overflow SED set decimal
- CMP compare (with accumulator) SEI set interrupt disable
- CPX compare with X STA store accumulator
- CPY compare with Y STX store X
- DEC decrement accumulator STY store Y
- DEX decrement X TAX transfer accumulator to X
- DEY decrement Y TAY transfer accumulator to Y
- EOR exclusive or (with accumulator) TSX transfer stack pointer to X
- INC increment accumulator TXA transfer X to accumulator
- INX increment X TXS transfer X to stack pointer
- INY increment Y TYA transfer Y to accumulator
- JMP jump
- JSR jump subroutine
- o=========o
- | Y. Tips |
- o=========o
- - Wanna know roughly where the BASIC program ends? Print the 'pointer to end of array variable area':
- PRINT PEEK(50)PEEK(49)
- It returns two decimal numbers. Each must be converted to hex. Example: "57 160" means "57A0_hex".
- - MLM's and TMP don't mix! They probably use the same memory locations. The MLM from the cartridge "Action Replay Mk. 4" does not. But be careful w/ SYS commands though.
- - For Kernal routines: page 272 & 273 from "Programmers reference guide" [2].
- - For alphabetically ordered description of all mnemonics: appendix A on page 281 - 293 from [1].
- - Insert waiting routine. It waits until the current scanline is out from the viewable screen area [8] [3]. See "Compute's Programming the Commodore 64" page 68: this routine waits until bit 8 of the raster line becomes 1, indicating bottom of the screen is reached. In BASIC:
- WAIT 53265,128
- Remark: this ain't no delay routine!
- Version in Assembly? [see: https://www.lemon64.com/forum/viewtopic.php?p=919957#919957]:
- ;Wait until raster line is 255
- loop01 LDA $D011 ;= 53265_dec
- AND %10000000 ;Set A to x000 0000
- CMP %10000000 ;Cmp A with 1xxx xxxx (128_dec)
- BEQ loop01
- In [3] the Assembly equivalent of this is this:
- loop lda $d011
- bpl loop
- - Load file from disk into memory (TMP does not support the pseudo-op ".binary" from TMPx): https://codebase64.org/doku.php?id=base:loading_a_file
- - Determine end address of data LOAD-ed [lemon64.com/forum/viewtopic.php?t=75660]: $00AE-$00AF [6], [10].
- o===============o
- | X. References |
- o===============o
- [1] "Commodore 64/128 Assembly language programming" by Mark Andrews, Howard W. Sams & Co. publ., ISBN 0-672-22244-5, First ed. (1986).
- [2] "C64 programmer's reference guide", Commodore Business Machines and Howard W. Sams and Co. publ., First ed. (1983).
- [3] Example of self modifying code:
- http://retro64.altervista.org/blog/6502-assembly-language-quick-overview-with-commodore-64-programming-examples/
- [4] "Machine language for the C64, 128, and other Commodore computers" by Jim Butterfield, Prentice Hall publ., ISBN 0-89303-652-8 (1986).
- [5] General programming skills/tips:
- https://codebase64.org/doku.php
- [6] HTML C64 memory map by Joe Forster:
- https://sta.c64.org/cbm64mem.html
- [7] HTML Kernal mem map by Joe Forster (jump table):
- https://sta.c64.org/cbm64krnfunc.html
- [8] Some coding:
- http://retro64.altervista.org/blog/simple-but-effective-commodore-64-basic-coding
- [9] "Programming the C64 the definitive guide", Raetro Collin West, Compute! Publications Inc., ISBN 0-942386-50-7 (1985).
- [10] "Mapping the C64", Sheldon Leemon, Compute! Publications Inc., ISBN 0-942386-23-X (1984).
- [11] All opcodes:
- www.masswerk.at/6502/6502_instruction_set.html
Add Comment
Please, Sign In to add comment