1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
/* Explanation of byte-reversing in ARM assembler
for PC only (uses cursor control codes)
*/
#include <stdio.h>
static void cls()
{
printf("\033[2J");
}
static void up(int n)
{
while (n > 0)
{ printf("\033[1A"); --n;
}
}
static void pause()
{
fprintf(stderr, "Please press <Return> to proceeed ");
while( fgetc(stdin) != '\n' );
}
static void prologue()
{
printf("\
AMAZING FACTS ABOUT THE ARM - Reversing the bytes in a word\n\
\n\
This function reverses the bytes in a word. The method was discovered in\n\
1986 following a competition between ARM programmers; it requires just 4\n\
instructions and 1 work register. A method using only 3 instructions per\n\
word reversed was also found, but it has some set-up overhead and uses a\n\
2nd register. Can you re-discover this method?\n\
\n\
Later, the C compiler was 'taught' to generate exactly the instructions\n\
needed, from C source. Check this claim using armcc -S -DREV byterev.c\n\
and examining the assembly code file produced.\n\
\n\
unsigned long reverse(unsigned long v)\n\
{ unsigned long t;\n\
t = v ^ ((v << 16) | (v >> 16)); /* EOR r1,r0,r0,ROR #16 */\n\
t &= ~0xff0000; /* BIC r1,r1,#&ff0000 */\n\
v = (v << 24) | (v >> 8); /* MOV r0,r0,ROR #8 */\n\
return v ^ (t >> 8); /* EOR r0,r0,r1,LSR #8 */\n\
}\n\
\n\
To see the method in action, press <Return>. Each time you press <Return>\n\
one step of the reversal process will be executed. The values displayed\n\
are symbolic, starting with the input word D C B A.\n\
\n");
}
static void prelude()
{
printf("\
AMAZING FACTS ABOUT THE ARM - Reversing the bytes in a word\n\
\n\
unsigned long reverse(unsigned long v)\n\
{ unsigned long t;\n\
t = v ^ ((v << 16) | (v >> 16)); /* EOR r1,r0,r0,ROR #16 */\n\
t &= ~0xff0000; /* BIC r1,r1,#&ff0000 */\n\
v = (v << 24) | (v >> 8); /* MOV r0,r0,ROR #8 */\n\
return v ^ (t >> 8); /* EOR r0,r0,r1,LSR #8 */\n\
}\n\
\n");
}
static void show_state_1()
{
printf("\
v / r0 t / r1 original input in v/r0\n\
\n\
+---+---+---+---+ +---+---+---+---+\n\
| D | C | B | A | | x | x | x | x |\n\
+---+---+---+---+ +---+---+---+---+\n\
\n\n\n\n\n\n\n");
}
static void show_state_2()
{
printf("\
v / r0 t / r1 state after executing \n\
\n\
+---+---+---+---+ +---+---+---+---+ t = v ^ ((v<<16) | (v>>16));\n\
| D | C | B | A | |D^B|C^A|B^D|A^C|\n\
+---+---+---+---+ +---+---+---+---+ EOR r1,r0,r0,ROR #16\n\
\n\n\n\n\n\n\n");
}
static void show_state_3()
{
printf("\
+---+---+---+---+ +---+---+---+---+ t &= ~0xff0000; \n\
| D | C | B | A | |D^B| 0 |B^D|A^C|\n\
+---+---+---+---+ +---+---+---+---+ BIC r1,r1,#&ff0000 \n\
\n\n\n\n\n\n\n");
}
static void show_state_4()
{
printf("\
+---+---+---+---+ +---+---+---+---+ v = (v << 24) | (v >> 8);\n\
| A | D | C | B | |D^B| 0 |B^D|A^C|\n\
+---+---+---+---+ +---+---+---+---+ MOV r0,r0,ROR #8 \n\
\n\n\n\n\n\n\n");
}
static void show_state_5()
{
printf("\
+---+---+---+---+ +---+---+---+---+ v = v ^ (t >> 8); \n\
\n\
+---+-^-+-^-+-^-+---+ +---+---+---+---+ EOR r0,r0,r1,LSR #8\n\
|D^B| 0 |B^D|A^C|\n\
+---+---+---+---+\n\
\n\
+---+---+---+---+\n\
| A | B | C | D | (original input was: D C B A)\n\
+---+---+---+---+\n\
\n");
}
int main()
{
cls();
prologue();
pause();
cls();
prelude();
show_state_1();
pause();
up(13);
show_state_2();
pause();
up(11);
show_state_3();
pause();
up(11);
show_state_4();
pause();
up(11);
show_state_5();
pause();
fputc('\n', stdout);
return( 0 );
}
|