--- /dev/null
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+/* Test case supplied by Sergei Trofimovich */
+
+/*
+ * Real life example (MSDOS file INFO.EXE) has code like this
+ *
+ * I don't know why author/compiler done code like this. Only guess:
+ * guess 1 (strong :]):
+ * This archaic code was used by dynamic memory regeneration
+ * handler (according to code around it's called from
+ * interrupt handler).
+ *
+ * guess 2: cache flush (whether processors had caches at that time?)
+ *
+ * a disasmed snippet:
+ *
+ * mov byte ptr [bx], 0FFh
+ * sti
+ * mov cx, 0FFFFh ; 65535
+ * rep lods byte ptr es:[si]
+ * jcxz short somewhere_1 ; it seems code could be
+ * ; interrupted here
+ *
+ * call something_2
+ * cmp dx, 4
+ * mov byte ptr [bx], 0
+ * jmp somewhere_3
+ */
+
+#define GET_BIT(var, bit_no) ((var >> bit_no) & 1)
+
+static char sz_eflags[] = " "; // 8 spaces
+static void pp_eflags (unsigned int _8bits_eflags)
+{
+ assert (_8bits_eflags >= 0);
+ assert (_8bits_eflags <= 0xFF);
+ sz_eflags[0] = GET_BIT(_8bits_eflags, 7) ? 'S' : ' ';
+ sz_eflags[1] = GET_BIT(_8bits_eflags, 6) ? 'Z' : ' ';
+ sz_eflags[3] = GET_BIT(_8bits_eflags, 4) ? 'A' : ' ';
+ sz_eflags[5] = GET_BIT(_8bits_eflags, 2) ? 'P' : ' ';
+ sz_eflags[7] = GET_BIT(_8bits_eflags, 0) ? 'C' : ' ';
+}
+
+#define EMIT_CALL(dir_insn, insn, in_eax, in_esi, in_eflags, out_eax, out_esi, out_eflags, count) \
+ asm volatile( \
+ "movl %3, %%eax \t\n" \
+ "sahf \t\n" /* loading our eflags */ \
+ "movl %4, %%eax \t\n" \
+ "movl %5, %%esi \t\n" \
+ "movl %6, %%ecx \t\n" \
+ \
+ dir_insn "\t\n" \
+ insn "\t\n" \
+ \
+ /* return result */ \
+ "movl %%eax, %0 \t\n" \
+ "lahf \t\n" \
+ "movl %%eax, %1 \t\n" \
+ "movl %%esi, %2 \t\n" \
+ : "=d"(out_eax), \
+ "=b"(out_eflags), \
+ "=r"(out_esi) \
+ \
+ : "m"(in_eflags), \
+ "m"(in_eax), \
+ "m"(in_esi), \
+ "q"(count) \
+ \
+ : "%eax", "%esi", "%ecx", "cc" /* we mess up EFLAGS */);
+
+const signed char b_mem_buff[] = {-4, -3, -2, -1, 0xaa, 1, 2, 3, 4};
+const signed long l_mem_buff[] = {-4, -3, -2, -1, 0xaa, 1, 2, 3, 4};
+const signed short w_mem_buff[] = {-4, -3, -2, -1, 0xaa, 1, 2, 3, 4};
+
+const int lens[] = { 4, 3, 2, 1, 0, 0, 1, 2, 3, 4};
+
+int main ()
+{
+ const signed char * b_center = (signed char *) memchr(b_mem_buff, 0xaa, sizeof (b_mem_buff));
+ const signed char * w_center = (signed char *) memchr(w_mem_buff, 0xaa, sizeof (w_mem_buff));
+ const signed char * l_center = (signed char *) memchr(l_mem_buff, 0xaa, sizeof (l_mem_buff));
+
+ int insn;
+ for (insn = 0; insn < 4; ++insn) //b,w[rep/addr],d,w[addr/rep]
+ {
+ int idx;
+ for (idx = 0; idx < sizeof (lens)/sizeof(lens[0]); ++idx)
+ {
+ unsigned int eflags;
+ unsigned int eax = 0x12348765;
+ unsigned int esi;
+ const char * i_name = NULL;
+ switch (insn)
+ {
+ case 0: //b
+ esi = (unsigned int) b_center;
+ i_name = "lodsb";
+ break;
+ case 1: //w
+ esi = (unsigned int) w_center;
+ i_name = "lodsw[rep/addr]";
+ break;
+ case 2: //d
+ esi = (unsigned int) l_center;
+ i_name = "lodsl";
+ break;
+ case 3: //w
+ esi = (unsigned int) w_center;
+ i_name = "lodsw[addr/rep]";
+ break;
+ }
+
+ eflags = 0;
+ pp_eflags ((eflags >> 8) & 0xFF); // scratching off AH
+ printf ("REP %s (EAX = %08X, EFLAGS = %s) => ", i_name, eax, sz_eflags);
+
+ unsigned int resulting_eflags = 0;
+ unsigned int resulting_eax = 0;
+ unsigned int resulting_esi;
+
+ int len = lens[idx];
+ int df = (idx >= (sizeof(lens)/sizeof(lens[0]))/2);
+ switch (insn)
+ {
+ case 0: //b
+ if (df)
+ {
+ EMIT_CALL("cld",
+ "rep lodsb",
+ eax, esi, eflags, resulting_eax, resulting_esi, resulting_eflags,
+ len);
+ }
+ else
+ {
+ EMIT_CALL("std",
+ "rep lodsb",
+ eax, esi, eflags, resulting_eax, resulting_esi, resulting_eflags,
+ len);
+ }
+ break;
+ case 1: //w[rep/addr]
+ if (df)
+ {
+ EMIT_CALL("cld",
+ // "rep lodsw",
+ // explicit: rep-pref addr-pref op
+ ".byte 0x66,0xf3,0xad",
+ eax, esi, eflags, resulting_eax, resulting_esi, resulting_eflags,
+ len);
+ }
+ else
+ {
+ EMIT_CALL("std",
+ // "rep lodsw",
+ // explicit: rep-pref addr-pref op
+ ".byte 0x66,0xf3,0xad",
+ eax, esi, eflags, resulting_eax, resulting_esi, resulting_eflags,
+ len);
+ }
+ break;
+ case 2: //d
+ if (df)
+ {
+ EMIT_CALL("cld",
+ "rep lodsl",
+ eax, esi, eflags, resulting_eax, resulting_esi, resulting_eflags,
+ len);
+ }
+ else
+ {
+ EMIT_CALL("std",
+ "rep lodsl",
+ eax, esi, eflags, resulting_eax, resulting_esi, resulting_eflags,
+ len);
+ }
+ break;
+ case 3: //w[addr/rep]
+ if (df)
+ {
+ EMIT_CALL("cld",
+ // "rep lodsw",
+ // explicit: rep-pref addr-pref op
+ ".byte 0xf3,0x66,0xad",
+ eax, esi, eflags, resulting_eax, resulting_esi, resulting_eflags,
+ len);
+ }
+ else
+ {
+ EMIT_CALL("std",
+ // "rep lodsw",
+ // explicit: rep-pref addr-pref op
+ ".byte 0xf3,0x66,0xad",
+ eax, esi, eflags, resulting_eax, resulting_esi, resulting_eflags,
+ len);
+ }
+ break;
+ }
+ printf ("DF = %d, count = %2d ", df, len);
+ pp_eflags ((resulting_eflags >> 8) & 0xFF); // scratching off AH
+ printf ("(EAX = %08X, EFLAGS = %s)\n", resulting_eax, sz_eflags);
+ }
+ }
+ return 0;
+}
--- /dev/null
+REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 0, count = 4 (EAX = 123487FD, EFLAGS = )
+REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 0, count = 3 (EAX = 123487FE, EFLAGS = )
+REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 0, count = 2 (EAX = 123487FF, EFLAGS = )
+REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 0, count = 1 (EAX = 123487AA, EFLAGS = )
+REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 0, count = 0 (EAX = 12348765, EFLAGS = )
+REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 1, count = 0 (EAX = 12348765, EFLAGS = )
+REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 1, count = 1 (EAX = 123487AA, EFLAGS = )
+REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 1, count = 2 (EAX = 12348701, EFLAGS = )
+REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 1, count = 3 (EAX = 12348702, EFLAGS = )
+REP lodsb (EAX = 12348765, EFLAGS = ) => DF = 1, count = 4 (EAX = 12348703, EFLAGS = )
+REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 4 (EAX = 1234FFFD, EFLAGS = )
+REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 3 (EAX = 1234FFFE, EFLAGS = )
+REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 2 (EAX = 1234FFFF, EFLAGS = )
+REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 1 (EAX = 123400AA, EFLAGS = )
+REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 0 (EAX = 12348765, EFLAGS = )
+REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 0 (EAX = 12348765, EFLAGS = )
+REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 1 (EAX = 123400AA, EFLAGS = )
+REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 2 (EAX = 12340001, EFLAGS = )
+REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 3 (EAX = 12340002, EFLAGS = )
+REP lodsw[rep/addr] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 4 (EAX = 12340003, EFLAGS = )
+REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 0, count = 4 (EAX = FFFFFFFD, EFLAGS = )
+REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 0, count = 3 (EAX = FFFFFFFE, EFLAGS = )
+REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 0, count = 2 (EAX = FFFFFFFF, EFLAGS = )
+REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 0, count = 1 (EAX = 000000AA, EFLAGS = )
+REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 0, count = 0 (EAX = 12348765, EFLAGS = )
+REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 1, count = 0 (EAX = 12348765, EFLAGS = )
+REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 1, count = 1 (EAX = 000000AA, EFLAGS = )
+REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 1, count = 2 (EAX = 00000001, EFLAGS = )
+REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 1, count = 3 (EAX = 00000002, EFLAGS = )
+REP lodsl (EAX = 12348765, EFLAGS = ) => DF = 1, count = 4 (EAX = 00000003, EFLAGS = )
+REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 4 (EAX = 1234FFFD, EFLAGS = )
+REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 3 (EAX = 1234FFFE, EFLAGS = )
+REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 2 (EAX = 1234FFFF, EFLAGS = )
+REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 1 (EAX = 123400AA, EFLAGS = )
+REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 0, count = 0 (EAX = 12348765, EFLAGS = )
+REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 0 (EAX = 12348765, EFLAGS = )
+REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 1 (EAX = 123400AA, EFLAGS = )
+REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 2 (EAX = 12340001, EFLAGS = )
+REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 3 (EAX = 12340002, EFLAGS = )
+REP lodsw[addr/rep] (EAX = 12348765, EFLAGS = ) => DF = 1, count = 4 (EAX = 12340003, EFLAGS = )