Monday, December 28, 2015

Day 11: Juventus supporters can't jump!!!! (Part 2)


Today we will see briefly the conditional jumps, or branches. The name branch comes from the fact the code may or may not jump to a certain  location in memory, depending if a condition is true or not. Branching is the equivalent of the Basic IF GOTO construct.


The Status Register as I wrote yesterday, is the onboard cpu register which stores some flags. The flags are side-effects of instructions. Normally instructions will manipulate and store the data in the accumulator, but depending on the result the CPU will set (put to 1) or reset (put to 0) some bits in this register.


The most important bits of the Status Register are:


Zero Flag
Every instructions that results in a zero, including transfers to accumulator or the x and y registers, will set this flag to 1, while any other result will set it to 0.


Carry Flag
Indicates if a mathematical instruction result in a situation where you will have to carry its most significant byte to another byte. It’s not the same as the overflow flag.


Overflow Flag
Indicates when the result of the operation sets the 7th bit. It’s a more restricted case of the Carry Flag.


Negative Flag
Indicates if the result is to be considered “negative”.


There are three other flags that are not used with branching, but they are present in the Status Register.


Decimal Flag,
Iit’s used to set the computer mathematical operations in “decimal” mode. Normally the 6510 will operate on bits with normal binary maths. If the decimal flag is set then the CPU will instead use the encoding and rules of Binary Coded Decimal, which trades off some ram (every byte coded in BCD will store only one out of 100 values instead of one out of 255, so it’s less compact) for getting more precise calculations.


Break Flag,
To be used to test if the processor returned from a BRK (break) instruction. I don’t know much about this flag yet.


Interrupt flag,
This  indicates if the CPU is currently executing an interrupt sequence. Interrupts are special ways a machine has to hijack control from a central program to handle important events like input or output operations (for example, when the user presses a button or when the TV finishes rendering a screen).


How and why to test for the flags


The Zero Flag
Testing for the zero flag is useful, for example, in situations where you have to test a FOR-style loop or when you do comparisons on bytes.


BEQ
with BEQ you test on the result of the previous operation being EQUAL to zero (Z  = 1)


   LDX    #$20
LOOP
   DEX
   BEQ    EXIT
   JMP    LOOP
EXIT
   ...


BNE
with BNE you test on the result of the previous operation  being NOT EQUAL to zero (Z = 0)


   LDX    #$20
LOOP
   DEX
   BNE    LOOP
   ...


Note that a comparison between two numbers can also set the zero flag if both numbers are equal.


For BEQ:


LDX    #$20
LDA    #$20
STX    $03FF
CMP    $03FF
BEQ    OK
...


For BNE:


LDX    #$20
LDA    #$21
STX    $03FF
CMP    $03FF
BNE    OK
...


The Negatifve Flag.
The Negative flag is useful, again, for countdowns, or is useful too in mathematical operations or other comparisons. You can test the Negative Flag with the following operations:


BMI
You use this to test if the result is negative (N = 1)


LDX    #$20
LDA    #$1F
STX    $03FF
CMP    $03FF
BMI    OK
...


BPL
You use this to test if the result is positive (N = 0)


LDX    #$20
LDA    #$21
STX    $03FF
CMP    $03FF
BPL    OK
...


The Carry Flag.
The Carry flag is useful with mathematical calculations. With an 8 bit computer you are not limited to work on 8 bit values, but you can chain those values to represent an higher precision number spending a bit more memory. Note that the Carry flag is automatically used by several mathematical operations as well. You can also see a bit more info on the C64 Wiki.


BCS
By now you can imagine that Branch on Carry Set branches when the Carry flag is set (C = 1)


LDA    #$FF
ADC    #$01
BCS    OK
...


BCC
Branch on carry clear instead jumps only if the Carry flag is reset (C = 0)


LDA    #$FE
ADC    #$01
BCC    OK
...


The Overflow Flag
There is a more limited number of instructions that will set the overflow flag, actually there are only two mathematical instructions (ADC and SBC) that will set this (and the BIT comparison instruction, but apparently BIT is rarely used). The Overflow flag is set when a 7-bit operation makes the number overflow in the 8th bit. If you add 1 to 127, you will obtain 128, which is represented like this: 10000000. In that case the ADC will remind you that, if you are using 7-bit precision numbers, to check the overflow flag if you need to test for SIGNED numbers, but you can ignore this flag instead if you are using UNSIGNED numbers. As usual, the C64 wiki explains stuff better than me.


BVS
Branch on Overflow Set (V = 1)


LDA    #$7F
ADC    #$01
BVS    OK
...


BVC
Branch on Overflow Clear (or “reset”) (V = 0)


LDA    #$7E
ADC    #$01
BVC    OK
...


The following is the code I used to test the various snippets.


*=$0810
PREAMBLE
       CLD
MAIN ; you can change the parts between MAIN and KO
       LDA     #$7F
       ADC     #$01
       BVC     OK
KO ; if your calculation is wrong the program should print two black @'s
       LDA     #$00
       STA     $0400
       STA     $0401
       LDX     #$00     
       STX     $D800
       STX     $D801
       RTS
OK ; if your calculation is correct the code should print two white A's
       LDA     #$01    
       STA     $0400
       STA     $0401
       LDX     #$01     
       STX     $D800
       STX     $D801
       RTS

; The following is how the machine stores the SYS 2080 command on
; line 10 of the Basic interpreter
; 10 SYS 2064

*=$801
       BYTE    $0B, $08, $0A, $00, $9E, $20, $32, $30, $36, $34, $00, $00, $00

No comments:

Post a Comment