User Tools

Site Tools


sd-8516_assembly_language

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
sd-8516_assembly_language [2026/01/27 06:01] appledogsd-8516_assembly_language [2026/01/29 12:09] (current) appledog
Line 41: Line 41:
 Let's dive in to the basic idea behind SD-8516 assembly language programming! If you've ever programmed before, it's similar but different to a high level language. It is similar because there are functions and commands that take operands, and it is different because the functions are very simple building blocks, and there are only a limited number of integer variables that you can use. Let's dive in to the basic idea behind SD-8516 assembly language programming! If you've ever programmed before, it's similar but different to a high level language. It is similar because there are functions and commands that take operands, and it is different because the functions are very simple building blocks, and there are only a limited number of integer variables that you can use.
  
-Firstly, there is a basic idea of how code should be written that is built into the structure of the ISA (instruction set architecture). This first idea is that of "Load-Store Architecture". The SD-8516 uses a load-store architecture. This means that data is read from and written to using only one command. There is no other command that can load or save data to and form memory. These commands are LD and ST (load and store). Following this command is operand number one, such as LDA which means "load into A," or LDB which means "load into B". Secondly are the ST operations, or "STore", such as STA or STB. These commands store from the A or B variable into memory.+The first concept is "Load-Store Architecture". The SD-8516 uses a load-store architecture. This means that data is read from and written to registers, operated on inside registers, and then written back out to memory. There are no memory to memory operations and registers can only be loaded and saved.
  
-Examples include:+The commands to load and store are LD and ST (load and store) followed by the register and an operand. For example,
  
 +       ; * LDA means "load into A,"
 +       ; * LDB means "load into B".
 +       
        LDA #56             ; Load the decimal number 56 into the variable A.        LDA #56             ; Load the decimal number 56 into the variable A.
        LDA [#56]           ; Load the value in memory location #56 into the variable A.        LDA [#56]           ; Load the value in memory location #56 into the variable A.
-       +
 That's it for load operations. You can load a variable with a number either from memory or from a number directly. You cannot load a variable from another variable. This is invalid: That's it for load operations. You can load a variable with a number either from memory or from a number directly. You cannot load a variable from another variable. This is invalid:
  
Line 105: Line 108:
 == Lesson 5: Flow Control (Branching) == Lesson 5: Flow Control (Branching)
 * Lesson 5: Flow Control (Branching) * Lesson 5: Flow Control (Branching)
-* Time: min+* Time: 10 min
 * Learn: Assembler Labels, CMP, JZ, RET * Learn: Assembler Labels, CMP, JZ, RET
  
Line 114: Line 117:
         CMP A, B         CMP A, B
         JZ @equal         JZ @equal
 +    
     not_equal:     not_equal:
         LDC $01   ; error code #1         LDC $01   ; error code #1
         RET         RET
 +    
     equal:     equal:
         LDC $00   ; no error         LDC $00   ; no error
Line 125: Line 128:
 The program loads the word (two bytes) at $00 ($00 and $01) into A, and the word at $02 ($02 and $03) into B. Then it compares them. If they are equal, the zero flag is set. Depending on this we set our return code, which here by convention is C. But it could be anything. We have thus demonstrated the ability to compare registers and make a decision on program contorl flow based on that comparison. This has applications everywhere, from making sure a cursor is within the limits of the screen, to testing if a character is uppercase or lowercase, and many, so many applications that we cannot list them here. The program loads the word (two bytes) at $00 ($00 and $01) into A, and the word at $02 ($02 and $03) into B. Then it compares them. If they are equal, the zero flag is set. Depending on this we set our return code, which here by convention is C. But it could be anything. We have thus demonstrated the ability to compare registers and make a decision on program contorl flow based on that comparison. This has applications everywhere, from making sure a cursor is within the limits of the screen, to testing if a character is uppercase or lowercase, and many, so many applications that we cannot list them here.
  
-What is show here is the fundamental flow control idea; compare and JZ if equal. Fall-through is the not-equal case. You could also use JNZ instead and fall-through the "is equal" case. Now you know how to control the flow of your programs!+CMP is the fundamental flow control operation. Compare two registers and JZ if equal. Fall-through is the not-equal case. You could also use JNZ instead and fall-through the "is equal" case. Now you know how to control the flow of your programs! 
 + 
 +=== How CMP affects flags 
 +CMP works by doing a simple test: 
 + 
 +        CMP A, B           ; We are doing A - B! 
 + 
 +Yes that's right, it's doing A - B, but it isn't doing it to store the value in A. It's testing if the result is 0 or not. If the result is zero, it sets the zero flag; ZF = 1. If it's not equal, then it is either ABOVE or BELOW zero. Imagine CMP 5,5 versus CMP 5,10 versus CMP 10,5: 
 + 
 +        CMP 5, 5           ;  5 -  5 =  0. Aha, a zero! ZF = 1 
 +        CMP 5, 10          ;  5 - 10 = -5. No zero. ZF = 0 
 +        CMP 10, 5          ; 10 -  5 =  5. No zero. ZF = 0 
 + 
 +So because it's equal, it produces a zero. Seeing the zero, the CPU sets the zero flag. Then you can control program flow by JZ (jump-if-zero) and JNZ (jump-if-not-zero). 
 + 
 +But there is more! As you see above, there are actually three situations that can occurr. It can be equal, or it can be less than zero, or above zero. You will notice that if A is less than B, the number is negative -- or, "less than". And, if the number in A is greater than B, then A-B produces a positive number, which is "greater than" zero. So it means A is greater than zero! This is why it's called CMP or "compare". It compares if A is greater than, equal to, or less than B. And, we can test that by looking at the carry flag. The rule is, if you need to "borrow", you do not set carry. 
 + 
 +        CMP 5, 5           ;  5 -  5 =  0.  No borrow --> carry is set:     CF = 1 
 +        CMP 5, 10          ;  5 - 10 = -5. Yes borrow --> carry is NOT set: CF = 0 
 +        CMP 10, 5          ; 10 -  5 =  5.  No borrow --> carry is set:     CF = 1 
 + 
 +Therefore, if carry is set, we know that A is less than B. 
 + 
 +But wait! There's more! 
 + 
 +        CMP 5, 5           ;  5 -  5 =  0. Not negative. N flag not set. 
 +        CMP 5, 10          ;  5 - 10 = -5. Yes negative. N flag set! 
 +        CMP 10, 5          ; 10 -  5 =  5. Not negative. N flag NOT set! 
 + 
 +So you can also use the N flag. So here is the situation: 
 + 
 +* If ZF=1 then A and B are equal. 
 +* If ZF = 0, then look at CF or NF 
 +** If CF is set, A is greater than B. 
 +** If NF is set, A is less than B. 
 + 
 +There you go! You can do this now, to branch on each condition: 
 + 
 +* JZ @A_equals_B 
 +* JC @A_greater_than_B 
 +* JN @A_less_than_B 
 + 
 +This is the foundation of how an IF statement works, or the ternary operator in C. 
 + 
 + 
 +== Lesson 6: The Boring Lesson 
 +* Lesson 6: The Boring Lesson 
 +* Time: 5-10 min 
 +* Learn: AND, OR, XOR, NOT 
 + 
 +The problem with computer science is that sometimes you have to learn some very boring things and you might not understand why they are important until later. Please understand that this is lesson #6, a fundamental lesson, and even if you find it boring, it will all work out for the best -- //trust me bro.// 
 + 
 +=== AND 
 +AND is a classic logic gate. When two signals are 1, it shows result 1. I.E. 1 and 1 is 1. If one of the signals is down (like, an actual electrical signal in a wire) then the result is zero. This is OFTEN but not always an analogy for a light switch. There is always power in your house (A is 1) but only when the switch is ON (=1) is the light on. So you need 1 power and 1 switch and when they are both ON, then the light is ON. If they are both off, then what happens? Nothing! Absolutely nothing! Watch: 
 + 
 +        LDA 1 
 +        LDB 1 
 +        AND A, B           ;  A now is 1 (1 and 1 is 1). 
 +     
 +        LDC 1 
 +        LDD 0 
 +        AND C, D           ;  C is now 0 (one of the switches is off). 
 +     
 +        LDE 0 
 +        LDF 1 
 +        AND E, F           ;  E is now 0 (one of the switches is off). 
 +     
 +        LDG 0 
 +        LDI 0 
 +        AND G, I           ;  G is now 0 (both switches are off). 
 + 
 +And is often displayed as an easy to read table: 
 +|   AND   | 
 +| | 0 | 1 | 
 +| 0 | 0 | 0 | 
 +| 1 | 0 | 1 | 
 + 
 +The AND means "result 1, only when x AND y are 1". 
 + 
 +=== Binary 
 +Now wrap your head around the power of binary! 
 + 
 +        LDA 0b01000111     ; 7 in binary 
 +        LDD 0b00010110     ; 6 in binary 
 +        AND A, D           ; A is now what? 0b00000110 
 + 
 +The bits in A that were also set in D remain. The bits that weren't set, ain't. Why is this useful? If you're using bits to hold status, or you want to test the value of a bit, you can do this: 
 + 
 +        LDA 0b01000111     ; some status register 
 +        LDD 0b00000100     ; Test for bit 3 
 +        AND A, D           ; A is now 0b00000100 
 +        JNZ @bit_3_is_set 
 +        JZ @bit_3_is_not_set 
 + 
 +Since if bit 3 is not set, AND A, D produces a zero, you can branch flow control based on bits. So for example, if your CPU has a "someone pressed a key" flag, you can test for that and handle the keypress by testing if rhe bit is on. This is just like checking if A = 5. Except you're checking a bit instead of an integer.
                  
 +Other commands that work in a similar way are OR, XOR, and NOT.
 +
 +=== OR
 +OR works by saying "Set the bit if either A or B is set." So it will be 1 unless both are zero. Thats useful for detecting thieves. If any one of the laser traps detect a thief, the alarm has to go off. Not all of them at once, but any one, anywhere, and the alarms go off! That's how OR works.
 +
 +=== XOR
 +XOR is "Exclusive" or. This means if the bits are the same, it's 0, if they're DIFFERENT, it's 1. This can be used to perform some surprising tricks. But as long as you understand the basic principle...
 +
 +* 0b00010001
 +* 0b00010010
 +* XOR
 +* 0b00000011
 +
 +The bits that were the same are 0, the bits that are diffrent are 1. Please don't ask me why this is useful, i'm sure i'll remember why later. Ha.
 +
 +=== NOT
 +Finally, NOT. Not inverts a number.
 +* 0b00000001 ; This is a 1.
 +* NOT
 +* 0b11111110; This is 254 in decimal or FE in hex. Commonly written as #254 or $FE in assembler convention. Or 0xFE. Or FEh.
  
 +Why is NOT useful? NOT gives you the negative version minus one. So to make a number negative. NOT it and add one. In the case of 1, this is FF. This means you had a zero, subtracted one, and it //rolled over// to FF. So FF is negative one! We will explain negative numbers later. For now, FF is 255. Not -1. But, well, that's what NOT is for.
  
 +=== The End of the Boring Lesson
 +If this lesson was confusing I'm sorry. The fact is you're not going to understand binary logic until later when you see it in action and see how it actually is used. For now, just try to remember the basic ideas. Or, failing that, just remember that there is an AND, and OR, an XOR, and a NOT. Everything else is based on those.
 +    
 == Appendix I: Registers == Appendix I: Registers
 There are sixteen general purpose registers available for use> Here they are, with a short comment on name and purpose. Of course, since they're general purpose, there is nothing separating one register from another except convention. You can feel free to use this guide, or use them any way you like. There are sixteen general purpose registers available for use> Here they are, with a short comment on name and purpose. Of course, since they're general purpose, there is nothing separating one register from another except convention. You can feel free to use this guide, or use them any way you like.
sd-8516_assembly_language.1769493718.txt.gz · Last modified: by appledog

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki