Clarification of MikroC code for conversion to Assembly.

Thread Starter

MaxHeadRoom

Joined Jul 18, 2013
28,619
I am in the process of converting a program from MikroC to ASM.
I am using the MikroC manual for assistance.
So far most seems to be fairly obvious as to what is being achieved.

But there is one function that I would like to get cleared up rather than guess.
It is the function of F0 and F1 in the following.
It does not appear to appear anywhere else in the code.

unsigned char enc_new;
unsigned char enc_last;


if(enc_new.F1 != enc_last.F0) mpos++;
else mpos--;
enc_last = enc_new;

if(PORTA.F0) pins.F0 = 1;
if(PORTA.F1) pins.F1 = 1;

What actually are F0/F1 doing?
Any help appreciated.
Max.
 

Thread Starter

MaxHeadRoom

Joined Jul 18, 2013
28,619
Another question for clarification on how these two consecutive 'if' instructions would be parsed.


// 1. updates encoder to see if motor has moved, records it position
enc_new = (PORTA & 0b00000011); // get the 2 encoder bits
if(enc_new != enc_last)
{
if(enc_new.F1 != enc_last.F0) mpos++; // record new motor position
else mpos--;
enc_last = enc_new;
}
I understand the If and else If, if used..
But how is the two 'if' instructions before the last else treated?
Max.
 

nsaspook

Joined Aug 27, 2009
13,086
C:
if(enc_new != enc_last)
{
    if(enc_new.F1 != enc_last.F0)
        mpos++; // record new motor position
    else
        mpos--;
    enc_last = enc_new;
}
 

Thread Starter

MaxHeadRoom

Joined Jul 18, 2013
28,619
Thanks, but as far as C is concerned I have a problem following the statement logic.
The shown code answer appears identical to the one in my question.
I see two IF statements following each other, my question is how are they collectively or sequentially treated?
Max.
 

bogosort

Joined Sep 24, 2011
696
I see two IF statements following each other, my question is how are they collectively or sequentially treated?
Adding a few more braces might help make the logic clearer:
C:
if(enc_new != enc_last)
{
    if (enc_new.F1 != enc_last.F0) {  mpos++; }
    else { mpos--; }

    enc_last = enc_new;
}
In English: When the value in enc_new equals the value in enc_last, all of the code is skipped and program execution continues after the last brace. Otherwise (the values are not equal), the value in mpos will either be incremented or decremented depending on whether enc_few.F1 equals enc_last.F0 or not. In either case, enc_last will be set to the value of enc_new.

With or without the extra braces, how do we know that the 'else' belongs to the inner 'if'? The compiler (or a human reading the code) figures this out by looking for blocks of code, which designate the scope of a group of statements.

The explicit way to define a block is with balanced curly braces, like those belonging to the outer 'if': the braces tell the compiler (and human) that every statement contained within belongs to a single block with its own scope (e.g., any variables declared in the block will be valid only within the block). In your example, the block is controlled by the outer 'if' -- so, when the condition is false, the entire block is skipped.

But C also has the notion of implicit blocks. Every 'if', 'else if', and 'else' statement has an associated block. When one of these blocks has multiple statements, we use braces to delimit the block. But the braces are optional if the block has only one (or zero) statements, as there's no ambiguity as to where the block begins and ends. So, if you see an 'if' followed by a statement without any curly braces, then you know that single statement is its own block, whose execution is controlled by the 'if' just above it. For more complicated expressions, it's just a matter of matching 'else's to their respective 'if's, paying attention to explicit and implicit blocks.

C:
if (A)
  if (B)
  {
    foo = 1;
    bar = 1;

    if (C)
      quux = 1;
    else // belongs to if(C)
      quux = 2;
  }
  else // belongs to if(B)
    foo = 2;
else // belongs to if(A)
{
  foo = 2;
  bar = 2;
}
A compiler will have no problem parsing the code above, but -- for humans'-sake -- it's best to use explicit braces, even if they're optional. They obviate the need for the "//belongs to" comments, and they protect against future bugs introduced by adding extra statements to one-statement blocks.
 

MrChips

Joined Oct 2, 2009
30,720
As a rule, when I am writing my own code, I do not leave out the braces, even when they contain a single statement. In fact, I always enter all pairs of braces and then fill in the statements afterwords:
C:
if ( )
  {
  }
else
  {
  }
Furthermore, when I anticipate that there will be nested structures, I comment each brace:
C:
if ( sunny )
  { // sunny
  } // sunny
else
  { // not sunny
  } // not sunny
 

Thread Starter

MaxHeadRoom

Joined Jul 18, 2013
28,619
@bogsort Appears to be the only one that has understood what I am looking for and has answered it, I am not really interested writing C code, I am much more comfortable in Assembly, I just needed an expanded interpretation of what the intention by the author of the program in this particular instance was trying to achieve in order to convert it.
The C manuals I consulted did not appear to help.
Unfortunately the author, Roman, who was also a member here, does not appear to have been around since 2013.
Max.
 

nsaspook

Joined Aug 27, 2009
13,086
The point of these Beautifier programs is to help you read C code and to understand the intention of the author of the program.

This is a functional C program.

Code:
#include<stdio.h>
int a = 256;int main(){for(char b[a+a+a],
*c=b ,*d=b+ a ,*e=b+a+a,*f,*g=fgets(e,(b[
a]=b [a+a] =a- a,a) , stdin);c[0]=a-a,f=c
,c=d ,d=e ,e=f, f= g,g =0,g = fgets(e,a+a
-a+ a -a+a -a+ a- +a,stdin ),f +a-a ; pu\
tchar(+10)) { for( int h= 1,i=1,j, k=0 ,l
=e[0]==32,m,n=0,o=c [ 0]== 32, p, q=0;d[q
];j=k,k=l,m=n,n=o,p=(j)+(k* 2 )+(l =(i = 
e[ q]&&i ) &&e[q +1 ]== 32,l*4)+(m* 8 )+(
16*  n  )+(  o  =(h =c[ q]&&h)&&c[q+1]== 
32,o* (16+16) )+0-0 +0, putchar(" ......"
/*\  (  |||  )  |/|/ / */".')|)\\\\\\\\'"
"" "|||"   "|||" "|'" ")|)\\\\\\\\'/|/(/"
"(/'/|/\\|\\|'/|/(/(/'/|/\\|\\|"[d[q++]==
32?p:0]));}}/* typographic tributaries */
Code:
#include<stdio.h>

int a = 256;
int main() {
  for (char b[a + a + a],
    * c = b, * d = b + a, * e = b + a + a, * f, * g = fgets(e, (b[
      a] = b[a + a] = a - a, a), stdin); c[0] = a - a, f = c, c = d, d = e, e = f, f = g, g = 0, g = fgets(e, a + a -
      a + a - a + a - a + a - +a, stdin), f + a - a; pu\ tchar(+10)) {
    for (int h = 1, i = 1, j, k = 0, l = e[0] == 32, m, n = 0, o = c[0] == 32, p, q = 0; d[q]; j = k, k = l, m = n, n = o, p = (j) + (k * 2) + (l = (i =
        e[q] && i) && e[q + 1] == 32, l * 4) + (m * 8) + (
        16 * n) + (o = (h = c[q] && h) && c[q + 1] ==
        32, o * (16 + 16)) + 0 - 0 + 0, putchar(" ......"
        /*\  (  |||  )  |/|/ / */
        ".')|)\\\\\\\\'"
        ""
        "|||"
        "|||"
        "|'"
        ")|)\\\\\\\\'/|/(/"
        "(/'/|/\\|\\|'/|/(/(/'/|/\\|\\|" [d[q++] ==
          32 ? p : 0
        ]));
  }
} /* typographic tributaries */
 

MrChips

Joined Oct 2, 2009
30,720
@bogsort Appears to be the only one that has understood what I am looking for and has answered it, I am not really interested writing C code, I am much more comfortable in Assembly, I just needed an expanded interpretation of what the intention by the author of the program in this particular instance was trying to achieve in order to convert it.
The C manuals I consulted did not appear to help.
Unfortunately the author, Roman, who was also a member here, does not appear to have been around since 2013.
Max.
I fully understood your perspective.
I posted my comment for two reasons:
1) if anyone is planning on writing C code
2) if you wanted to decipher C code, in which case you can insert the braces to make the code more comprehendable.
 
Top