Shop OBEX P1 Docs P2 Docs Learn Events
Assembly Effects — Parallax Forums

Assembly Effects

parskoparsko Posts: 501
edited 2006-08-02 16:08 in Propeller 1
Hi, me again...

After having started to learn (or better said "read") about assembly, I have become confused. I don't quite understand the 4 effects; how they are used? When to use them? What they are for? I suppose I am asking for an explanation of the two flags themselves. It seems that these effects are used all over in assembly, so understanding them would be paramount to understanding assembly code.

Would anyone care to explain them (in laymen terms please)?

Thanks,

-Parsko

Comments

  • Paul BakerPaul Baker Posts: 6,351
    edited 2006-07-31 16:21
    In the propeller there are two flags, the Z and C. Z stands for Zero, and it's typical use is that whenever a result is 0, the bit is set. C stands for Carry, and it's typical use is to indicate whenever there is an overflow (this is when an operation causes a "wrap around", for instance in unsigned subtaction 0-1 = -1, but since the number is unsigned an overflow occurs because the resultant number is the maximum positive number possible for the number of bits (32 for the propeller)).

    These two values can be combined to achieve some interesting mathmatical properties of numbers, for instance subtracting two numbers you can determine whether they are equal (Z is set), the first number is greater than the second number (Z is clear, C is clear), or the second number is greater than the first number (Z is clear, C is set). You can then use these results to do conditional operations (such as only performing an operation if two numbers are equal).

    The powerful thing about Propeller assembly is you have complete control over when the flags are affected, so you could affect the flags, do some operations where you don't affect the flags, then do conditional operations based on the flags that you set way back in the execution when you specified them to be set.

    What is also nice is the use of the conditional execution, where an instuction which has a conditional fills the program stream but is only executed if the condition is true. This practically eliminates the need for conditional jumps and also has the benifit of making multi-path execution take the same amount of time regardless of which path is executed. In comparison on the SX, if you had two different operations to do (for instance) based on whether the result is zero, and you need the execution time to be identical regardless of which branch was executed, you would typically have to add some NOPs in there to make it so the execution time is the same; on the propeller this isn't nessesary.

    For a listing of how each instruction affects the flags (if you specify them to be affected) look at page 350-351.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ...

    Post Edited (Paul Baker) : 7/31/2006 4:29:34 PM GMT
  • parskoparsko Posts: 501
    edited 2006-07-31 17:04
    Wow, that is a new concept to me. If you add two numbers and the result is 0, why/how would you set the Z flag?

    If you set a Z flag, what exactly does it mean to the operation being executed? Does it perform another operation (the Z "operation") other than the primary operation?

    These confuse me TONS right now, but so did Timing Diagrams until about 4 hours ago!!

    -Parsko
  • Paul BakerPaul Baker Posts: 6,351
    edited 2006-07-31 17:40
    No, I was speaking of subtraction, which is the ordinary means for comparing two numbers. But it is possible to add two numbers to get 0, in the Propeller if you add 4,294,967,295 and 1 the result is 0, thats because 4,294,967,295 is $FFFF_FFFF and adding·1 to it causes an overflow and it wraps around to 0.

    Flags are set according to the operation executed when you specify you want them to be set, for mathmatical operations, the Z flag indicates the result is 0. But for non-mathmatical operations, the Z flag can take on an additional meaning, though with the propeller it basically just means the result is 0, for instance if you do a MOV operation, if the value moved is 0 and you have specified a wz affect, the Z flag will be set. The C flag has alot more nuanced of a definition when doing non-mathmatical operations. For instance if you perform a COGINIT with a wc affect, C will be set if there were no free cogs were availible. If you do an ABS with wc affect, the C flag will be set if the original value was negative.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ...
  • parskoparsko Posts: 501
    edited 2006-08-01 19:42
    I'm starting to grasp the flags, but still a few questions:

    These flags are simply flags, right? I mean, each assy routine has only two flags to modify. If I modify one flag, it applies to all code following it?

    If I have code, such as:
    test _pins, #$20 wc

    The WC does exactly what?
    Where is the flag stored?
    How do I "un-set" the flag (in a case, for instance, where I have a loop, and I want it cleared)?
    The C flag is set AFTER the test, correct?

    A "WZ" denotes the "Z flag is modified".
    Does that mean it is "toggled" to the opposite state from its present state?

    EDIT: OOOORRRRR, does it reset itself when the WZ flag is specified. I mean, even if it was true, and you are in a line where it is specified, it doesn't matter what the state currently is, it will still write it as true?

    That's it for now...
    -Parsko

    Post Edited (parsko) : 8/1/2006 9:28:58 PM GMT
  • Paul BakerPaul Baker Posts: 6,351
    edited 2006-08-01 21:45
    Each cog has it's own set of the Zero and Carry flag. To specify an affect on a particular instruction, means that the flag will be set according to how the instruction will affect that particular flag.

    For your example "test _pins, #$20 wc", the instruction will perform _pins - $20 (but will not store the result in _pins), if the result is less than zero (ie _pins < $20), then the Carry flag will be set, if the result is greater than or equal to zero (_pins >= $20), the Carry flag will be cleared. The value contained within the Carry flag is set/cleared according to the instruction, irregardless of what it's value was before the instruction was executed.

    The flags are used in combination with the conditionals, so if you later specify "if_nc mov B, A", the contents of location A will be copied to location B only if _pins was greater than $20. This line of code can be the next immediate instruction, or any number of instructions later where the instructions between the two do not specify wc. IOW the flags are set/cleared only when you explicitly specify that the flag is affected.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ...

    Post Edited (Paul Baker) : 8/1/2006 9:48:48 PM GMT
  • parskoparsko Posts: 501
    edited 2006-08-02 06:48
    So,

    To confirm:

    If I have set (state=1) a flag by specifying a "WZ" at the end of a line, I would DE-set (state=0) the same flag by specifying "WZ" again?

    It's like a lightswitch, everytime to see it in code, it toggles the state from the present state?

    Thanks again, I figured out my algorithm, did the pseudo code BY HAND, so I know it works, now I must apply.

    -Luke
  • IanMIanM Posts: 40
    edited 2006-08-02 11:29
    parsko said...
    So,

    To confirm:

    If I have set (state=1) a flag by specifying a "WZ" at the end of a line, I would DE-set (state=0) the same flag by specifying "WZ" again?

    It's like a lightswitch, everytime to see it in code, it toggles the state from the present state?

    Thanks again, I figured out my algorithm, did the pseudo code BY HAND, so I know it works, now I must apply.

    -Luke

    The effect flags don't toggle the C or Z flags they enable the C or Z flags. In most microcontrollers, instructions that can change the C or Z flags (or other flags) will always affect the flag. That doesn't mean if the Z flag was 0 before an instruction execution it will always be 1 after the instruction execution. It does mean that if the Z flag was 0 before the instruction execution it will be 1 only if the result of the execution is zero otherwise it will stay 0. Similarly if the Z flag was 1 before instruction execution and the result of the execution is zero, the Z flag will stay 1.

    In the propeller you use WZ and WC to enable the instruction to set or clear the Z or C flag if that is the outcome of the execution of the instruction (as in most microcontrollers). If you don't specify WZ or WC that the Z and C flag don't change at all for that instruction.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Ian Mitchell
    www.research.utas.edu.au
  • Paul BakerPaul Baker Posts: 6,351
    edited 2006-08-02 15:10
    Ok let me show you by example.

    Say we have the instruction "ADD A, B· wc, wz"
    which is read as: "add the contents of B to A, store the result in A and·affect the Carry and Zero flags according to the result stored in A"

    Now lets plug in some values:
    Contents of A   Contents of B  Result stored in A   Zero flag   Carry flag  (contents of flags are after the ADD)
    $0000_0000      $0000_0000       $0000_0000             1           0
    $1234_5678      $1234_5678       $2468_ACF0             0           0
    $8000_0000      $8000_0001       $0000_0001             0           1
    $8000_0000      $8000_0000       $0000_0000             1           1
    

    These four example represent all possible combinations of the flags, what the contents of the flags were before this instruction occured do not matter, they are overwritten without any concern over what thier previous contents were.

    In the first example 0+0=0, which is clearly 0, so the Zero flag is set, no wraparound occured, so the Carry flag is cleared.

    In the second example the result is not 0 so the Zero flag is cleared, no wraparound occured, so the Carry flag is cleared.

    In the third example, the result is $1_0000_0001, but this value cannot be held in the register, so the top bit is chopped of, this is called wraparound or "carry", so the Carry flag is set, the wrapped around value is not 0 so the Zero flag is cleared.

    In the last example, the result is $1_0000_0000, the top bit is chopped off, so the Carry flag is set, the resultant chopped version is 0, so the Zero flag is set.

    I hope these examples help clear things for you.

    P.S.· On occasion you will see terms "wrap-around", "carry" and "overflow". These terms are refering to the same thing, whenever an operation causes a result which cannot be contained within the number of bits in a register.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ...

    Post Edited (Paul Baker) : 8/2/2006 3:22:07 PM GMT
  • Kaos KiddKaos Kidd Posts: 614
    edited 2006-08-02 15:20
    I take it that the code must account for the state of the flags before the statement was executed, right?
    For example, if your looking to code for a 'non default' condition, then test for that non default condition, your code must either explicitly set the default condition or explicitly test for the non default condition. I take it is's all a matter of how you approch your code design that determins the steps needed to setup for a test.
    Right? Or am I way out there in left field?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

    Propeller + Hardware - extra bits for the bit bucket =· 1 Coffeeless KaosKidd

    ·
  • Paul BakerPaul Baker Posts: 6,351
    edited 2006-08-02 15:32
    The Z and C flags are not general purpose flags, and shouldn't be seen as such. They should be seen as boundry checks for the operation of the code executed on the cog. If you perform a math operation on numbers and the result has gone past what the register can contain, you have exceeded a boundry and this is expressed in the Carry flag. The Zero flag is most used in loops, if you want to loop 5 times, you load a register with 5, and on each loop it gets decremeted by 1, when the register contains the value of 1, it is decremeted to 0, the Z flag gets set, and the DJNZ instruction knows that it has now done as many loops as it needs to do and doesn't loop again.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ...
  • parskoparsko Posts: 501
    edited 2006-08-02 16:08
    Paul said...
    what the contents of the flags were before this instruction occured do not matter, they are overwritten without any concern over what thier previous contents were
    Paul also said...
    They should be seen as boundry checks for the operation of the code executed on the cog

    yeah.gifyeah.gifyeah.gif

    Those statements did it. I grasp it, now I simply have to implement it somewhere. Well said everyone, well said!

    -Luke

    PS - I probably should have put some emoticons between the emoticons...
Sign In or Register to comment.