diff --git a/nemu/include/cpu/decode.h b/nemu/include/cpu/decode.h
index 91e211eaf4c33670302446d115c3c6a57ea4a513..e8c61911585dcfa9bc3559f750a01f1f8fc140cf 100644
--- a/nemu/include/cpu/decode.h
+++ b/nemu/include/cpu/decode.h
@@ -71,7 +71,8 @@ extern DecodeInfo decoding;
 #define id_src2 (&decoding.src2)
 #define id_dest (&decoding.dest)
 
-#define make_DHelper(name) void concat(decode_, name) (vaddr_t *eip)
+#define make_DHelper_funcname(name) concat(decode_, name)
+#define make_DHelper(name) void make_DHelper_funcname(name) (vaddr_t *eip)
 typedef void (*DHelper) (vaddr_t *);
 
 make_DHelper(I2E);
diff --git a/nemu/include/cpu/exec.h b/nemu/include/cpu/exec.h
index 21b8e537e66b9cb79eb7d4f5a56c55fff7a2b4d3..a11fff15cb0438a4aeed861d71fdc79b39328c00 100644
--- a/nemu/include/cpu/exec.h
+++ b/nemu/include/cpu/exec.h
@@ -3,7 +3,8 @@
 
 #include "nemu.h"
 
-#define make_EHelper(name) void concat(exec_, name) (vaddr_t *eip)
+#define make_EHelper_funcname(name) concat(exec_, name)
+#define make_EHelper(name) void make_EHelper_funcname(name) (vaddr_t *eip)
 typedef void (*EHelper) (vaddr_t *);
 
 #include "cpu/decode.h"
diff --git a/nemu/include/macro.h b/nemu/include/macro.h
index 80a72ccff98918596cd8bc1a76a1f9e5b0187ac5..a08559bd06a48f4d980fcabcccf2bb60730c4c98 100644
--- a/nemu/include/macro.h
+++ b/nemu/include/macro.h
@@ -4,8 +4,7 @@
 // Implements origin `str()` macro. Extremely bad naming.
 #include <rlib/macro.hpp>
 
-#define concat_temp(x, y) x ## y
-#define concat(x, y) concat_temp(x, y)
+#define concat(x, y) RLIB_MACRO_CAT(x, y)
 #define concat3(x, y, z) concat(concat(x, y), z)
 #define concat4(x, y, z, w) concat3(concat(x, y), z, w)
 #define concat5(x, y, z, v, w) concat4(concat(x, y), z, v, w)
diff --git a/nemu/src/cpu/decode/decode.cc b/nemu/src/cpu/decode/decode.cc
index 71c4a4ca776ceca330a199eead28f95cf3b2a807..036c330174487f6841004d929d43ddf06bd37003 100644
--- a/nemu/src/cpu/decode/decode.cc
+++ b/nemu/src/cpu/decode/decode.cc
@@ -9,7 +9,8 @@ void decoding_set_jmp(bool is_jmp) {
   decoding.is_jmp = is_jmp;
 }
 
-#define make_DopHelper(name) void concat(decode_op_, name) (vaddr_t *eip, Operand *op, bool load_val)
+#define make_DopHelper_funcname(name) concat(decode_op_, name)
+#define make_DopHelper(name) void make_DopHelper_funcname(name) (vaddr_t *eip, Operand *op, bool load_val)
 
 /* Refer to Appendix A in i386 manual for the explanations of these abbreviations */
 
@@ -92,7 +93,7 @@ static inline make_DopHelper(r) {
  * Rd
  * Sw
  */
-static inline void decode_op_rm(vaddr_t *eip, Operand *rm, bool load_rm_val, Operand *reg, bool load_reg_val) {
+static inline void make_DopHelper_funcname(rm)(vaddr_t *eip, Operand *rm, bool load_rm_val, Operand *reg, bool load_reg_val) {
   read_ModR_M(eip, rm, load_rm_val, reg, load_reg_val);
 }
 
@@ -113,101 +114,101 @@ static inline make_DopHelper(O) {
  * Ev <- Gv
  */
 make_DHelper(G2E) {
-  decode_op_rm(eip, id_dest, true, id_src, true);
+  make_DopHelper_funcname(rm)(eip, id_dest, true, id_src, true);
 }
 
 make_DHelper(mov_G2E) {
-  decode_op_rm(eip, id_dest, false, id_src, true);
+  make_DopHelper_funcname(rm)(eip, id_dest, false, id_src, true);
 }
 
 /* Gb <- Eb
  * Gv <- Ev
  */
 make_DHelper(E2G) {
-  decode_op_rm(eip, id_src, true, id_dest, true);
+  make_DopHelper_funcname(rm)(eip, id_src, true, id_dest, true);
 }
 
 make_DHelper(mov_E2G) {
-  decode_op_rm(eip, id_src, true, id_dest, false);
+  make_DopHelper_funcname(rm)(eip, id_src, true, id_dest, false);
 }
 
 make_DHelper(lea_M2G) {
-  decode_op_rm(eip, id_src, false, id_dest, false);
+  make_DopHelper_funcname(rm)(eip, id_src, false, id_dest, false);
 }
 
 /* AL <- Ib
  * eAX <- Iv
  */
 make_DHelper(I2a) {
-  decode_op_a(eip, id_dest, true);
-  decode_op_I(eip, id_src, true);
+  make_DopHelper_funcname(a)(eip, id_dest, true);
+  make_DopHelper_funcname(I)(eip, id_src, true);
 }
 
 /* Gv <- EvIb
  * Gv <- EvIv
  * use for imul */
 make_DHelper(I_E2G) {
-  decode_op_rm(eip, id_src2, true, id_dest, false);
-  decode_op_I(eip, id_src, true);
+  make_DopHelper_funcname(rm)(eip, id_src2, true, id_dest, false);
+  make_DopHelper_funcname(I)(eip, id_src, true);
 }
 
 /* Eb <- Ib
  * Ev <- Iv
  */
 make_DHelper(I2E) {
-  decode_op_rm(eip, id_dest, true, NULL, false);
-  decode_op_I(eip, id_src, true);
+  make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false);
+  make_DopHelper_funcname(I)(eip, id_src, true);
 }
 
 make_DHelper(mov_I2E) {
-  decode_op_rm(eip, id_dest, false, NULL, false);
-  decode_op_I(eip, id_src, true);
+  make_DopHelper_funcname(rm)(eip, id_dest, false, NULL, false);
+  make_DopHelper_funcname(I)(eip, id_src, true);
 }
 
 /* XX <- Ib
  * eXX <- Iv
  */
 make_DHelper(I2r) {
-  decode_op_r(eip, id_dest, true);
-  decode_op_I(eip, id_src, true);
+  make_DopHelper_funcname(r)(eip, id_dest, true);
+  make_DopHelper_funcname(I)(eip, id_src, true);
 }
 
 make_DHelper(mov_I2r) {
-  decode_op_r(eip, id_dest, false);
-  decode_op_I(eip, id_src, true);
+  make_DopHelper_funcname(r)(eip, id_dest, false);
+  make_DopHelper_funcname(I)(eip, id_src, true);
 }
 
 /* used by unary operations */
 make_DHelper(I) {
-  decode_op_I(eip, id_dest, true);
+  make_DopHelper_funcname(I)(eip, id_dest, true);
 }
 
 make_DHelper(r) {
-  decode_op_r(eip, id_dest, true);
+  make_DopHelper_funcname(r)(eip, id_dest, true);
 }
 
 make_DHelper(E) {
-  decode_op_rm(eip, id_dest, true, NULL, false);
+  make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false);
 }
 
 make_DHelper(setcc_E) {
-  decode_op_rm(eip, id_dest, false, NULL, false);
+  make_DopHelper_funcname(rm)(eip, id_dest, false, NULL, false);
 }
 
 make_DHelper(gp7_E) {
-  decode_op_rm(eip, id_dest, false, NULL, false);
+  make_DopHelper_funcname(rm)(eip, id_dest, false, NULL, false);
 }
 
 /* used by test in group3 */
 make_DHelper(test_I) {
-  decode_op_I(eip, id_src, true);
+  make_DopHelper_funcname(I)(eip, id_src, true);
 }
 
 make_DHelper(SI2E) {
   assert(id_dest->width == 2 || id_dest->width == 4);
-  decode_op_rm(eip, id_dest, true, NULL, false);
+  make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false);
   id_src->width = 1;
-  decode_op_SI(eip, id_src, true);
+  make_DopHelper_funcname(SI)(eip, id_src, true);
   if (id_dest->width == 2) {
     id_src->val &= 0xffff;
   }
@@ -215,16 +216,16 @@ make_DHelper(SI2E) {
 
 make_DHelper(SI_E2G) {
   assert(id_dest->width == 2 || id_dest->width == 4);
-  decode_op_rm(eip, id_src2, true, id_dest, false);
+  make_DopHelper_funcname(rm)(eip, id_src2, true, id_dest, false);
   id_src->width = 1;
-  decode_op_SI(eip, id_src, true);
+  make_DopHelper_funcname(SI)(eip, id_src, true);
   if (id_dest->width == 2) {
     id_src->val &= 0xffff;
   }
 }
 
 make_DHelper(gp2_1_E) {
-  decode_op_rm(eip, id_dest, true, NULL, false);
+  make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false);
   id_src->type = OP_TYPE_IMM;
   id_src->imm = 1;
   rtl_li(&id_src->val, 1);
@@ -234,7 +235,7 @@ make_DHelper(gp2_1_E) {
 }
 
 make_DHelper(gp2_cl2E) {
-  decode_op_rm(eip, id_dest, true, NULL, false);
+  make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false);
   id_src->type = OP_TYPE_REG;
   id_src->reg = R_CL;
   rtl_lr(&id_src->val, R_CL, 1);
@@ -244,23 +245,23 @@ make_DHelper(gp2_cl2E) {
 }
 
 make_DHelper(gp2_Ib2E) {
-  decode_op_rm(eip, id_dest, true, NULL, false);
+  make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false);
   id_src->width = 1;
-  decode_op_I(eip, id_src, true);
+  make_DopHelper_funcname(I)(eip, id_src, true);
 }
 
 /* Ev <- GvIb
  * use for shld/shrd */
 make_DHelper(Ib_G2E) {
-  decode_op_rm(eip, id_dest, true, id_src2, true);
+  make_DopHelper_funcname(rm)(eip, id_dest, true, id_src2, true);
   id_src->width = 1;
-  decode_op_I(eip, id_src, true);
+  make_DopHelper_funcname(I)(eip, id_src, true);
 }
 
 /* Ev <- GvCL
  * use for shld/shrd */
 make_DHelper(cl_G2E) {
-  decode_op_rm(eip, id_dest, true, id_src2, true);
+  make_DopHelper_funcname(rm)(eip, id_dest, true, id_src2, true);
   id_src->type = OP_TYPE_REG;
   id_src->reg = R_CL;
   rtl_lr(&id_src->val, R_CL, 1);
@@ -270,29 +271,29 @@ make_DHelper(cl_G2E) {
 }
 
 make_DHelper(O2a) {
-  decode_op_O(eip, id_src, true);
-  decode_op_a(eip, id_dest, false);
+  make_DopHelper_funcname(O)(eip, id_src, true);
+  make_DopHelper_funcname(a)(eip, id_dest, false);
 }
 
 make_DHelper(a2O) {
-  decode_op_a(eip, id_src, true);
-  decode_op_O(eip, id_dest, false);
+  make_DopHelper_funcname(a)(eip, id_src, true);
+  make_DopHelper_funcname(O)(eip, id_dest, false);
 }
 
 make_DHelper(J) {
-  decode_op_SI(eip, id_dest, false);
+  make_DopHelper_funcname(SI)(eip, id_dest, false);
   // the target address can be computed in the decode stage
   decoding.jmp_eip = id_dest->simm + *eip;
 }
 
 make_DHelper(push_SI) {
-  decode_op_SI(eip, id_dest, true);
+  make_DopHelper_funcname(SI)(eip, id_dest, true);
 }
 
 make_DHelper(in_I2a) {
   id_src->width = 1;
-  decode_op_I(eip, id_src, true);
-  decode_op_a(eip, id_dest, false);
+  make_DopHelper_funcname(I)(eip, id_src, true);
+  make_DopHelper_funcname(a)(eip, id_dest, false);
 }
 
 make_DHelper(in_dx2a) {
@@ -303,17 +304,17 @@ make_DHelper(in_dx2a) {
   sprintf(id_src->str, "(%%dx)");
 #endif
 
-  decode_op_a(eip, id_dest, false);
+  make_DopHelper_funcname(a)(eip, id_dest, false);
 }
 
 make_DHelper(out_a2I) {
-  decode_op_a(eip, id_src, true);
+  make_DopHelper_funcname(a)(eip, id_src, true);
   id_dest->width = 1;
-  decode_op_I(eip, id_dest, true);
+  make_DopHelper_funcname(I)(eip, id_dest, true);
 }
 
 make_DHelper(out_a2dx) {
-  decode_op_a(eip, id_src, true);
+  make_DopHelper_funcname(a)(eip, id_src, true);
 
   id_dest->type = OP_TYPE_REG;
   id_dest->reg = R_DX;
diff --git a/nemu/src/cpu/exec/exec.cc b/nemu/src/cpu/exec/exec.cc
index 460588107bd0415486ab3685e5945f21f2b92c5d..373d4c38ac3e58bae6684810dff88d3225d9395e 100644
--- a/nemu/src/cpu/exec/exec.cc
+++ b/nemu/src/cpu/exec/exec.cc
@@ -7,9 +7,9 @@ typedef struct {
   int width;
 } opcode_entry;
 
-#define IDEXW(id, ex, w)   {concat(decode_, id), concat(exec_, ex), w}
+#define IDEXW(id, ex, w)   {make_DHelper_funcname(id), make_EHelper_funcname(ex), w}
 #define IDEX(id, ex)       IDEXW(id, ex, 0)
-#define EXW(ex, w)         {NULL, concat(exec_, ex), w}
+#define EXW(ex, w)         {NULL, make_EHelper_funcname(ex), w}
 #define EX(ex)             EXW(ex, 0)
 #define EMPTY              EX(inv)
 
@@ -233,7 +233,7 @@ void exec_wrapper(bool print_flag) {
 #endif
 
   decoding.seq_eip = ori_eip;
-  exec_real(&decoding.seq_eip);
+  make_EHelper_funcname(real)(&decoding.seq_eip);
 
 #ifdef DEBUG
   int instr_len = decoding.seq_eip - ori_eip;
diff --git a/nemu/src/cpu/exec/prefix.cc b/nemu/src/cpu/exec/prefix.cc
index 7b112e8bfd63818fec1b54c309b2f1df71f5d29b..4e8898b449a3f258beacf90b9a010408acf7f1c0 100644
--- a/nemu/src/cpu/exec/prefix.cc
+++ b/nemu/src/cpu/exec/prefix.cc
@@ -4,6 +4,6 @@ make_EHelper(real);
 
 make_EHelper(operand_size) {
   decoding.is_operand_size_16 = true;
-  exec_real(eip);
+  make_EHelper_funcname(real)(eip);
   decoding.is_operand_size_16 = false;
 }