Week2
Week2
Links to 6502 instruction set:
https://www.masswerk.at/6502/6502_instruction_set.html
https://www.pagetable.com/c64ref/6502/?tab=2#
STA ($10),Y ; Y adds to the pointer
STA ($10,X) ; X selects a pointer starting at the base of 10
Math
Binary: Standard mode for single-byte math (8 bits) on signed or unsigned integers.
Decimal (limited): Each byte is treated as two decimal digits (upper 4 bits - tens, lower 4 bits - ones). Only addition and subtraction with ADC and SBC instructions are supported.
Addition (ADC | add with carry):
- Adds a value in the accumulator, another byte, and the Carry flag (borrow from previous addition).
-
Use CLC
to
clear the Carry flag before adding the least significant byte for multi-byte
addition.
- Overflow flag (V) sets if the signed result is outside the -128 to 127 range
Example:
LAD #$0A ; load 10 in A
CLC ; clear the flag just to make sure it’s clean
ABC #$05 ; Add 5 in A
BRK ; the result of 15 + 7 is now in A
Subtraction (SBC | subtract with carry):
- Subtracts a byte from the accumulator and inverts the Carry flag (acts as a borrow flag).
-
Set the Carry flag with SEC
before subtracting the least significant byte in multi-byte subtraction.
- Overflow flag (V) sets if the signed result is outside the -128 to 127 range.
Example: (We use the carry to help with the calculation here)
SED
LDA #$25
STA $00
LDA #$11
STA $01
LDA #$30
STA $10
LDA #$00
STA $11
SEC
LDA $00
SBC $10
STA $20
LDA $01
SBC $11
STA $21
Division: No dedicated instruction, but we use logical shift right (LSR) can effectively divide by two.
Example:
LDA #$0A ; Load 10 in A
LSR A ; Shift right (10/2)
BRK ; Result of 10/2 is now in A
Multiplication: No dedicated instruction, but we use arithmetic shift left (ASL) can effectively multiply by two.
Example:
LDA #$0A ; Load 10 in A
ASL A ; Shift left (10*2)
BRK ; Result of 10*2 is now in A
List of few shifting:
LSR (Logical Shift Right): Shifts bits right, with a zero filling the most significant bit. The least significant bit is shifted into the Carry flag.
ASL (Arithmetic Shift Left): Shifts bits left, with a zero filling the least significant bit. The most significant bit is shifted into the Carry flag.
ROR (Rotate Right): Rotates bits right, with the Carry flag being rotated into the most significant bit and the least significant bit being shifted into the Carry flag.
ROL (Rotate Left): Rotates bits left, with the Carry flag being rotated into the least significant bit and the most significant bit being shifted into the Carry flag.
Bitwise Operations:
- Basic operations include AND, OR, XOR (EOR), Rotate (ROR/ROL), and Shift (LSR/ASL).
- NOT operation can be emulated using EOR with #$FF.
- BIT instruction performs AND, sets Z flag based on the result, and affects N and V flags based on operand bits.
Jumps, Branches, and Procedures
Jumps:
- Unconditional jumps move the program counter (PC) to a specific memory location.
- Two addressing modes are available:
o
Absolute addressing: Jumps to a specific fixed
address (e.g., JMP $f027
).
o
Indirect addressing: Jumps to the address stored
in another memory location (e.g., JMP
($6094)
)
Branches:
· Conditional jumps based on the status of processor flags.
· Branch to an address within -128 to +127 bytes relative to the current location. It can only go so far.
· List of available instructions:
BCC
: Branch if Carry flag ClearBCS
: Branch if Carry flag SetBEQ
: Branch on EQual (zero flag set)BNE
: Branch on Not Equal (zero flag clear)BMI
: Branch on MInus (negative flag set)BPL
: Branch on PLus (negative flag clear)BVC
: Branch on oVerflow flag V ClearBVS
: Branch on oVerflow flag V Set
Example
:
LDA #$10 ; store the color at A
LDY #$00 ; store 0 in Y
LOOP STA $0200,Y
INY
BNE LOOP ; go to LOOP is not zero (watching zero flag)
RTS
BRK
Procedures (Subroutines):
- Special code sections that can be called from other parts of the program.
- Used for modularity and code reuse.
- Key instructions:
o
JSR (Jump to
SubRoutine)
: Jumps to the procedure's starting address and pushes
the current PC onto the stack.
o
RTS (Return from
Subroutine)
: Pops the address from the stack and resumes
execution after the JSR
call.
- Return values:
o Passed back through registers or memory locations.
o Specific method depends on data type (e.g., registers for small integers, memory for strings).
This is the basic of how to controls the flow when coding in 6502.
After some basic of 6502. We are now looking in to the x86_64 Linux system the AArch64 system.
"Assembly language is a symbolic representation of machine language. It is therefore very architecture-specific.
Each instruction is represented by a short mnemonic word such as “LDR” for Load Register, “MOV” for move, or “MUL” for multiply, followed by (optional) arguments. The addressing mode is implied by the format of the arguments. Different assemblers use slightly different syntax."
An example of Hello world from each.
x86_64:
.text .globl _start _start: mov $len, %edx /* file descriptor: 1 is stdout */ mov $msg, %ecx /* message location (memory address) */ mov $1, %ebx /* message length (bytes) */ mov $4, %eax /* write is syscall #4 */ int $0x80 /* invoke syscall */ mov $0, %ebx /* exit status: 0 (good) */ mov $1, %eax /* kernel syscall number: 1 is sys_exit */ int $0x80 /* invoke syscall */ .data msg: .ascii "Hello, World!\n" len = . - msg
AArch64:
.text .globl _start _start: mov x0, 1 /* file descriptor: 1 is stdout */ adr x1, msg /* message location (memory address) */ mov x2, len /* message length (bytes) */ mov x8, 64 /* write is syscall #64 */ svc 0 /* invoke syscall */ mov x0, 0 /* status -> 0 */ mov x8, 93 /* exit is syscall #93 */ svc 0 /* invoke syscall */ .data msg: .ascii "Hello, world!\n" len= . - msg
They both have more set instruction than 6502. It's like a better and more powerful version of 6502. Both has more registers. They both name things differently but in the bigger picture they does the same thing. You can add different registers with some set instruction (specify width).
We look into Makefiles for both.
x86_64:
BINARIES=hello
all: ${BINARIES}
AS_ARGS=-g
hello: hello.s
as ${AS_ARGS} -o hello.o hello.s
ld -o hello hello.o
clean:
rm ${BINARIES} *.o || true
AArch64:
BINARIES=hello
AS=as
LD=ld
all: ${BINARIES}
loop: loop.s
${AS} -g -o loop.o loop.s
${LD} -o loop loop.o
clean:
hello: hello.s
${AS} -g -o hello.o hello.s
${LD} -o hello hello.o
clean:
rm ${BINARIES} *.o
They are use to help us to build our code. For x86_64 we are using the GAS syntax.
Comments
Post a Comment