EventHelix.com: CASE Tools; Real-time and Embedded System Design; Object Oriented Design
  Home  |  EventStudio System Designer 4.0  |  VisualEther Protocol Analyzer 1.0  Real-time Mantra  Contact Us

Home > Real-time Mantra > Embedded Design > C to Assembly Translation II
C to Assembly Translation II

We have covered the C calling convention and the compiler generated code in the previous article. This article will focus on the code generation for:

Code Generation for While Loop

The following example shows the code generation for a simple while loop. Also note that the function shown below does not generate the LINK and UNLK instructions as this function does not have local variables. Since A6 is not used as a frame pointer, parameter access is carried out by directly taking offsets from the stack pointer (A7).

Code Generation for While Loop
void copy_string(const char *source, char *destination)
{
     * Save registers on stack so that they can be used in this function
     MOVEM.L A1-A2, -(A7)
     * Move destination to address register A1 (Direct offset from A7)
     MOVEA.L 16(A7), A1
     * Move source to address register A2 (Direct offset from A7)
     MOVEA.L 12(A7), A2
  while(*destination++ = *source++);
     * Define the label L1 for beginning of loop
     * Copy the byte from source to destination and increment pointers
  L1 MOVE.B (A2)+, (A1)+
     * Branch if not equal to zero. If the value moved to the destination
     * is not zero, branch to L1 (i.e. stay in the while loop)
     * Exit while loop as soon as a zero is moved into the destination
     BNE.S L1
}
     * Restore the old values of A1 and A2 by popping them off the stack
     MOVEM.L (A7)+, A1-A2
     * Return back to caller
     RTS
      

Code Generation for For Loop

Code generation for the for loop is covered in the example given below.

Code Generation for For Loop
for (i=0; i < 100; i++)
{
  . . .
}
    
      * Data Register D2 is used to implement i.
      * Set D2 to zero (i=0)
      CLR.L D2
    
  L1  
      . . .
      * Increment i for (i++)
      ADDQ.L #1, D2
      * Check for the for loop exit condition ( i < 100)
      CMPI.L #100, D2
      * Branch to the beginning of for loop if less than flag is set
      BLT.S L1
      

Code Generation for Structure Access

The code generation for C structure access is covered here. The example shows the filling of a message structure. This function does not have LINK and UNLK as the local variable p_msg has been assigned to a register, so no space needs to be allocated for local variables on the stack.

Code Generation for Structure Access
typedef struct 
{
   UChar type;
   UChar sub_type;
   UShort source_id;
} MessageHeader;

typedef struct
{
   MessageHeader header;
   UChar status;
   UChar reason;
   UShort padding;
} StatusMessage; 
   
void send_status_message()
{
     * Save Address Register A1 on stack. Register A1 will be used for p_msg 
     MOVEA.L A1, -(A7)
   StatusMessage *p_msg;
   p_msg = maloc(sizeof(StatusMessage));
     * Push the size of StatusMessage on the stack
     * The instruction below is a special instruction of pushing effective address.
     * Here it is used as a quick mechanism of pushing a constant on the stack
     PEA.L 8
     * Call maloc
     JSR _maloc
     * Pop the parameter off the stack
     ADDQ.L #4, A7
     * _maloc returns in D0, this value is copied to A1
     MOVE.L D0, A1     
   p_msg->header.type = STATUS_MESSAGE;
     * Type is at offset 0 in the structure
     MOVE.B #100, (A1)
   p_msg->header.sub_type = 0;
     * Clear sub_type at offset 1
     CLR.B 1(A1)
   p_msg->header.source_id = TASK_ID;
     * source_id is at offset 2 and involves a word access
     MOVE.W #0x0A22, 2(A1)
   p_msg->status = SUCCESS;
     * Status field is at offset 4
     MOVE.B #1, 4(A1)
   p_msg->reason = NOTHING;
     * Reason field is at offset 5
     MOVE.L #1, 5(A1)
   send_message(STATUS_TASK_ID, p_msg);
     * Push p_msg on to the stack
     MOVE.L A1, -(A7)
     * Push STATUS_TASK_ID on to the stack
     MOVE.L #0x0B23, -(A7)
     * Invoke send_message
     JSR _send_message
     * Pop the parameters off the stack
     ADDQ.L #8, A7
     
}
    * Restore Address Register A1
    MOVEA.L (A7)+, A1
    RTS      

Code Generation for Array Indexing

The code below shows an instance of array indexing. The generated code is very inefficient because it leads to a multiply by structure size. This overhead can also be reduced by making the size of the structure a power of 2, i.e. 2, 4, 8, 16 etc. In such cases the compiler would replace the multiply with a shift instruction.

Code Generation for Array Indexing
typedef struct
{
    Ulong a;
    Ushort b;
} ABStructure;

for (i=0; i < 100; i++)
{
   abstructure[i].x = 0;
   . . .
}

     * Code for i = 0, D2 is used for i
     CLR.W D2
     * Move index i into D3
  L1 MOVE.W D2, D3
     * Multiply index with size of ABStructure to determine the offset for the indexed
     * structure
     MULS.W #6, D3
     * Base address of abstructure is in A5, add the offset in D3 to obtain the address
     * of the indexed structure entry and set it to zero
     CLR.L (A5, D3)
     . . .
     * i++
     ADDQ.W #1, D2
     * For loop comparison (i < 100)
     CMPI.W #100, D2
     * If less than 100, branch to loop start at L1
     BLT.S L1  

Most compilers will optimize the above code by directly incrementing the pointer in a loop. The optimized code and the generated assembly code are shown below. This optimization really speeds up array indexing in a loop as multiply/shifts are avoided.

Code Generation for Array Indexing (Optimized)
 // Effective C Code
ABStructure *ptr = &abstructure[0];
for (i=0; i < 100; i++)
{
   ptr->x = 0;
   . . .
   ptr++;
}
     * Store the base address of the array in Address Register A5
     LEA.L _abstructure, A5
     * Code for i = 0, D2 is used for i
     CLR.W D2
     * Code corresponding to ptr->x = 0;
  L1 CLR.L (A5)
     . . .
     * Code corresponding to ptr++
     * Add size of ABStructure to address in A5 (ptr)
     ADDQ.W #6, A5
     * i++
     ADDQ.W #1, D2
     * For loop comparison (i < 100)
     CMPI.W #100, D2
     * If less than 100, branch to loop start at L1
     BLT.S L1  
 

  Home  |  EventStudio System Designer 4.0  |  VisualEther Protocol Analyzer 1.0  Real-time Mantra  Contact Us
Copyright © 2000-2009 EventHelix.com Inc. All Rights Reserved.