/* Based on: http://www.ethernut.de/en/documents/arm-inline-asm.html min-max example: take a pair as input and move smaller value to min, larger value to max field. C and inline assembler versions Compile: gcc -o s01 sample01.c Run: ./s01 */ #include #include static volatile int val = 1024, val2, val3; typedef struct { ulong min; ulong max; } pair_t; // pair_t pair1, res1, res2, res3, res4, res5, res_ex; void main (int argc, char **argv) { pair_t *pair = (pair_t*)malloc(sizeof(pair_t)); pair_t *pair2 = (pair_t*)malloc(sizeof(pair_t)); pair->min = 7; pair->max = 5; fprintf(stderr, "Testing simple inline assembler programs\nValue = %d\n", val); { ulong t; fprintf(stderr, "BEFORE: pair min: %d\tpair max: %d\n", pair->min, pair->max); if (pair->min > pair->max) { t = pair->min; pair->min = pair->max; pair->max = t; } fprintf(stderr, "AFTER: pair min: %d\tpair max: %d\n", pair->min, pair->max); } pair->min = 7; pair->max = 5; { pair_t *res; fprintf(stderr, "BEFORE: pair min: %d\tpair max: %d\n", pair->min, pair->max); asm volatile(/* min-max example: move smaller value to min, larger value to max field Input: pair (C variable, pointing to a pair) Output: res (C variable, pointing to a pair) */ "\tLDR R0, [%[inp], #0] @ load first element of the pair into R0 \n" "\tLDR R1, [%[inp], #4] @ load first element of the pair into R0 (why the #4?)\n" "\tCMP R0, R1 @ compare the values\n" "\tBLE done%= @ min < max means: nothing to do\n" "\tMOV R3, R0 @ otw swap the values using R3 as temp reg\n" "\tMOV R0, R1\n" "\tMOV R1, R3\n" "done%=: STR R0, [%[inp], #0] @ now store the first value in min field\n" "\tSTR R1, [%[inp], #4] @ now store the second value in min field\n" "\tMOV %[result], %[inp] @ finally, return the pointer to the pair\n" : [result] "=r" (res) // the name 'result' in Asm is the same as the C var 'res', and it must be held in a register ("r") : [inp] "r" (pair) // the name 'inp' in Asm is the same as the C var 'pair', and it must be held in a register ("r") : "r0", "r1", "r3", "cc" ); // these register are modified by the above assembler code fprintf(stderr, "AFTER: pair min: %d\tpair max: %d\n", pair->min, pair->max); fprintf(stderr, "AFTER: res min: %d\tres max: %d\n", res->min, res->max); fprintf(stderr, "Note: the C variable 'res' (0x%x) is now an alias to the input variable 'pair' (0x%x); \nno space has been allocated for res, is this a bug in the program?\n", res, pair); pair->min = 1; fprintf(stderr, "After setting pair->min = 1 we have: pair min: %d\tpair max: %d\n", pair->min, pair->max); fprintf(stderr, "BUT also: res min: %d\tres max: %d\n", res->min, res->max); } *pair2 = *pair; fprintf(stderr, "We have copied the contents of pair into pair2: pair2 min: %d\tpair2 max: %d\n", pair2->min, pair2-> max); fprintf(stderr, "BUT these occupy different locations in memory: pair (0x%x) and pair2 (0x%x)\n", pair, pair2); { pair_t *pair3; fprintf(stderr, "What happens if we hadn't malloc'ed space for pair2?\n"); *pair3 = *pair; // expect a crash! } }