A
anon.asdf
Here's a reminder of duff's device:
/*************************************/
#include <stdio.h>
#define STEP 8
#define MAX_LEN STEP*4+1
#define SOURCE_LEN 28
int main(void)
{
char source[SOURCE_LEN] =
"abcdefghijklmnopqrstuvwxyz0";
char destination[MAX_LEN] = {0};
char *src_ptr;
char *dest_ptr;
char *lim;
int user_input;
printf("Enter a number between incl. 1 and %d\n"
"To quit enter: 0<ENTER>\n", SOURCE_LEN-1);
while ((scanf("%d", &user_input) > 0)
&& (user_input > 0)
&& (user_input < SOURCE_LEN)) {
src_ptr = source;
lim = source + user_input;
dest_ptr = destination;
switch (user_input % 8) {
case 0: do {*dest_ptr++ = *src_ptr++;
case 7: *dest_ptr++ = *src_ptr++;
case 6: *dest_ptr++ = *src_ptr++;
case 5: *dest_ptr++ = *src_ptr++;
case 4: *dest_ptr++ = *src_ptr++;
case 3: *dest_ptr++ = *src_ptr++;
case 2: *dest_ptr++ = *src_ptr++;
case 1: *dest_ptr++ = *src_ptr++;
} while (src_ptr < lim);
}
#if 0 /*** alternative ***/
switch (user_input % 8) {
do {*dest_ptr++ = *src_ptr++;
case 7: *dest_ptr++ = *src_ptr++;
case 6: *dest_ptr++ = *src_ptr++;
case 5: *dest_ptr++ = *src_ptr++;
case 4: *dest_ptr++ = *src_ptr++;
case 3: *dest_ptr++ = *src_ptr++;
case 2: *dest_ptr++ = *src_ptr++;
case 1: *dest_ptr++ = *src_ptr++;
case 0: ; } while (src_ptr < lim);
}
#endif
*dest_ptr = '\0';
puts(destination);
}
return 0;
}
/*************************************/
The switch itself scales horribly. At worst we encounter 8 compare-
operations until we reach the desired case.
Maby there is a better way of doing the switch statement: In
particular - the argument to the switch evaluates to an integer
between 0 and 7 (incl.) and now the question is: could we not use this
number as an offset to immediately jump the code to
the desired location.
goto la_0 - (user_input % 8)
// * sizeof("*dest_ptr++ = *src_ptr++;"instruction)
;
do {*dest_ptr++ = *src_ptr++;
la_7: *dest_ptr++ = *src_ptr++;
la_6: *dest_ptr++ = *src_ptr++;
la_5: *dest_ptr++ = *src_ptr++;
la_4: *dest_ptr++ = *src_ptr++;
la_3: *dest_ptr++ = *src_ptr++;
la_2: *dest_ptr++ = *src_ptr++;
la_1: *dest_ptr++ = *src_ptr++;
la_0: ; } while (src_ptr < lim);
The code snippet above shows the idea:
we jump to an address relative to out pivot-label la_0.
Example
If (user_input % 8) == 1, we
want to jump to "la_0 minus a few instructions" to land up at la_1.
Can something like this be done?
Can we get a label's address and subtract (or add) an integer to it?
Or are there other alternatives that don't need a label...?
Of course, there are issues involved:
What if the compiler thinks it's "clever" ?
what does the compiler do with the empty ; located at la_0 (of course
we do not want a nop)?
Thanks a thousand... I'm getting a cold duff from the fridge!
Kind regards,
Albert
/*************************************/
#include <stdio.h>
#define STEP 8
#define MAX_LEN STEP*4+1
#define SOURCE_LEN 28
int main(void)
{
char source[SOURCE_LEN] =
"abcdefghijklmnopqrstuvwxyz0";
char destination[MAX_LEN] = {0};
char *src_ptr;
char *dest_ptr;
char *lim;
int user_input;
printf("Enter a number between incl. 1 and %d\n"
"To quit enter: 0<ENTER>\n", SOURCE_LEN-1);
while ((scanf("%d", &user_input) > 0)
&& (user_input > 0)
&& (user_input < SOURCE_LEN)) {
src_ptr = source;
lim = source + user_input;
dest_ptr = destination;
switch (user_input % 8) {
case 0: do {*dest_ptr++ = *src_ptr++;
case 7: *dest_ptr++ = *src_ptr++;
case 6: *dest_ptr++ = *src_ptr++;
case 5: *dest_ptr++ = *src_ptr++;
case 4: *dest_ptr++ = *src_ptr++;
case 3: *dest_ptr++ = *src_ptr++;
case 2: *dest_ptr++ = *src_ptr++;
case 1: *dest_ptr++ = *src_ptr++;
} while (src_ptr < lim);
}
#if 0 /*** alternative ***/
switch (user_input % 8) {
do {*dest_ptr++ = *src_ptr++;
case 7: *dest_ptr++ = *src_ptr++;
case 6: *dest_ptr++ = *src_ptr++;
case 5: *dest_ptr++ = *src_ptr++;
case 4: *dest_ptr++ = *src_ptr++;
case 3: *dest_ptr++ = *src_ptr++;
case 2: *dest_ptr++ = *src_ptr++;
case 1: *dest_ptr++ = *src_ptr++;
case 0: ; } while (src_ptr < lim);
}
#endif
*dest_ptr = '\0';
puts(destination);
}
return 0;
}
/*************************************/
The switch itself scales horribly. At worst we encounter 8 compare-
operations until we reach the desired case.
Maby there is a better way of doing the switch statement: In
particular - the argument to the switch evaluates to an integer
between 0 and 7 (incl.) and now the question is: could we not use this
number as an offset to immediately jump the code to
the desired location.
goto la_0 - (user_input % 8)
// * sizeof("*dest_ptr++ = *src_ptr++;"instruction)
;
do {*dest_ptr++ = *src_ptr++;
la_7: *dest_ptr++ = *src_ptr++;
la_6: *dest_ptr++ = *src_ptr++;
la_5: *dest_ptr++ = *src_ptr++;
la_4: *dest_ptr++ = *src_ptr++;
la_3: *dest_ptr++ = *src_ptr++;
la_2: *dest_ptr++ = *src_ptr++;
la_1: *dest_ptr++ = *src_ptr++;
la_0: ; } while (src_ptr < lim);
The code snippet above shows the idea:
we jump to an address relative to out pivot-label la_0.
Example
If (user_input % 8) == 1, we
want to jump to "la_0 minus a few instructions" to land up at la_1.
Can something like this be done?
Can we get a label's address and subtract (or add) an integer to it?
Or are there other alternatives that don't need a label...?
Of course, there are issues involved:
What if the compiler thinks it's "clever" ?
what does the compiler do with the empty ; located at la_0 (of course
we do not want a nop)?
Thanks a thousand... I'm getting a cold duff from the fridge!
Kind regards,
Albert