diff --git a/nemu/include/cpu/decode.h b/nemu/include/cpu/decode.h
index 720c93fa456ec0ecb72c79c68d9329fc61130f23..26109f79cf4e092c6f919d456c30fd3fb3654e36 100644
--- a/nemu/include/cpu/decode.h
+++ b/nemu/include/cpu/decode.h
@@ -87,6 +87,7 @@ namespace DHelperImpl {
   make_DHelper(I_E2G);
   make_DHelper(I_G2E);
   make_DHelper(I);
+  make_DHelper(O);
   make_DHelper(r);
   make_DHelper(E);
   make_DHelper(setcc_E);
diff --git a/nemu/include/cpu/reg.h b/nemu/include/cpu/reg.h
index a0ee63680381e20a6acb65042c98db3d7635b3ab..0fd8c65de53aede981ae8557ea566eb5f55a4fd1 100644
--- a/nemu/include/cpu/reg.h
+++ b/nemu/include/cpu/reg.h
@@ -35,7 +35,7 @@ typedef union {
 extern CPU_state cpu;
 
 namespace cpu_eflags {
-  enum {CF = 0, PF, AF, ZF, SF, OF, SIZE_OF_EFLAGS};
+  enum {CF = 0, PF, AF, ZF, SF, OF, DF, SIZE_OF_EFLAGS};
   template <size_t Which>
   inline bool &get() {
     static bool actual_buffer[SIZE_OF_EFLAGS];
diff --git a/nemu/src/cpu/exec/all-instr.h b/nemu/src/cpu/exec/all-instr.h
index 9f47be6a63d25b5da666879a2cbfca54c997495d..7b965e3d746677d41fd43aff9146f14f317f16a0 100644
--- a/nemu/src/cpu/exec/all-instr.h
+++ b/nemu/src/cpu/exec/all-instr.h
@@ -8,6 +8,7 @@ make_EHelper(pop);
 make_EHelper(pusha);
 make_EHelper(popa);
 make_EHelper(leave);
+make_EHelper(movs);
 make_EHelper(movsx);
 make_EHelper(movzx);
 make_EHelper(cltd);
diff --git a/nemu/src/cpu/exec/arith.cc b/nemu/src/cpu/exec/arith.cc
index 7fbd98cf98ba34a72f12a2f06b8ca75466183940..f4ac3ff052719908631016cfac08cba62b6d8bca 100644
--- a/nemu/src/cpu/exec/arith.cc
+++ b/nemu/src/cpu/exec/arith.cc
@@ -60,37 +60,36 @@ namespace EHelperImpl {
   }
   
   make_EHelper(inc) {
-  	rtl_addi(&t2, &id_dest->val, 1);
-  	operand_write(id_dest, &t2);
-  	rtl_update_ZFSF(&t2, id_dest->width);
-  	rtl_xor(&t0, &id_dest->val, &id_src->val);
-  	rtl_not(&t0, &t0);
-  	rtl_xor(&t1, &id_dest->val, &t2);
-  	rtl_and(&t0, &t0, &t1);
-  	rtl_msb(&t0, &t0, id_dest->width);
-  	rtl_set_OF(&t0);
+    cpu_eflags::get<cpu_eflags::OF>() = id_dest->val == 0x7fffffff;
+
+  	++ id_dest->val;
+  	operand_write(id_dest, &id_dest->val);
+
+  	rtl_update_ZFSF(&id_dest->val, id_dest->width);
   
     print_asm_template1(inc);
   }
   
   make_EHelper(dec) {
-    rtl_subi(&t2, &id_dest->val, 1);
-  	operand_write(id_dest, &t2);
-  
-  	rtl_update_ZFSF(&t2, id_dest->width);
-  
-  	rtl_xor(&t0, &id_dest->val, &id_src->val);
-  	rtl_xor(&t1, &id_dest->val, &t2);
-  	rtl_and(&t0, &t0, &t1);
-  	rtl_msb(&t0, &t0, id_dest->width);
-  	rtl_set_OF(&t0);
-  
+    cpu_eflags::get<cpu_eflags::OF>() = id_dest->val == 0x80000000;
+
+  	-- id_dest->val;
+  	operand_write(id_dest, &id_dest->val);
+
+  	rtl_update_ZFSF(&id_dest->val, id_dest->width);
+
     print_asm_template1(dec);
   }
   
   make_EHelper(neg) {
-    TODO();
-  
+    cpu_eflags::get<cpu_eflags::CF>() = id_dest->val != 0;
+    cpu_eflags::get<cpu_eflags::OF>() = id_dest->val == 0x80000000;
+
+    id_dest->val = - id_dest->val;
+  	operand_write(id_dest, &id_dest->val);
+
+  	rtl_update_ZFSF(&id_dest->val, id_dest->width);
+
     print_asm_template1(neg);
   }
   
diff --git a/nemu/src/cpu/exec/data-mov.cc b/nemu/src/cpu/exec/data-mov.cc
index 78d7a61d8ef288ed240114bb733b045ba798a11b..c890af268f76ccc11e7d4f20f881696df417899e 100644
--- a/nemu/src/cpu/exec/data-mov.cc
+++ b/nemu/src/cpu/exec/data-mov.cc
@@ -102,4 +102,30 @@ namespace EHelperImpl {
     operand_write(id_dest, &id_src->addr);
     print_asm_template2(lea);
   }
+
+  make_EHelper(movs) {
+    // movsb, movsw, movsd
+
+    // address size is always 32bit.
+    const auto source_index = cpu.esi,
+      dest_index = cpu.edi;
+    
+    auto copy_bytes = 4;
+    if(decoding.opcode == 0xa4) {
+      // movsb
+      copy_bytes = 1;
+    }
+    else if(decoding.is_operand_size_16) {
+      // movsw
+      // r: dbt
+      copy_bytes = 2;
+    }
+    else {
+      // movsd
+    }
+
+    vaddr_write(dest_index, vaddr_read(source_index, 4), copy_bytes);
+    
+    print_asm_template2(movs);
+  }
 } // end namespace
diff --git a/nemu/src/cpu/exec/exec.cc b/nemu/src/cpu/exec/exec.cc
index 67ab9e7c1f81db6de5243a2b58826a7988a19fcc..3c67656de60b0c26d801a851b00a8a3dd5de09d2 100644
--- a/nemu/src/cpu/exec/exec.cc
+++ b/nemu/src/cpu/exec/exec.cc
@@ -111,7 +111,7 @@ opcode_entry opcode_table [512] = {
 	/* 0x98 */	EX(cwtl), EX(cltd), IDEX(I,call), EMPTY,
 	/* 0x9c */	EMPTY, EMPTY, EMPTY, EMPTY,
 	/* 0xa0 */	IDEXW(O2a, mov, 1), IDEX(O2a, mov), IDEXW(a2O, mov, 1), IDEX(a2O, mov),
-	/* 0xa4 */	EMPTY, EMPTY, EMPTY, EMPTY,
+	/* 0xa4 */  EX(movs), EX(movs), EMPTY, EMPTY,
 	/* 0xa8 */	IDEXW(I2a,test,1), IDEX(I2a,test), EMPTY, EMPTY,
 	/* 0xac */	EMPTY, EMPTY, EMPTY, EMPTY,
 	/* 0xb0 */	IDEXW(mov_I2r, mov, 1), IDEXW(mov_I2r, mov, 1), IDEXW(mov_I2r, mov, 1), IDEXW(mov_I2r, mov, 1),