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 Clear
  • BCS: Branch if Carry flag Set
  • BEQ: 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 Clear
  • BVS: 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

Popular posts from this blog

Project Stage 3

Week4

Week 3