diff --git a/py/asmarm.c b/py/asmarm.c
index 663f8615630553f2f91e609cdf8bb3c259734524..63963d2c0da854686dd01c1da03f47a5c5c161e3 100644
--- a/py/asmarm.c
+++ b/py/asmarm.c
@@ -55,7 +55,10 @@ void asm_arm_end_pass(asm_arm_t *as) {
 
 // Insert word into instruction flow
 STATIC void emit(asm_arm_t *as, uint op) {
-    *(uint*)asm_arm_get_cur_to_write_bytes(as, 4) = op;
+    uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 4);
+    if (c != NULL) {
+        *(uint32_t*)c = op;
+    }
 }
 
 // Insert word into instruction flow, add "ALWAYS" condition code
diff --git a/py/asmbase.c b/py/asmbase.c
index 848730593e0b5ad1b8769bb74c445d55390c5a09..c941e917b73f50d8de676db48c33c6452d48cd5e 100644
--- a/py/asmbase.c
+++ b/py/asmbase.c
@@ -59,17 +59,16 @@ void mp_asm_base_start_pass(mp_asm_base_t *as, int pass) {
 }
 
 // all functions must go through this one to emit bytes
-// if as->pass < MP_ASM_PASS_EMIT, then this function returns dummy_data
+// if as->pass < MP_ASM_PASS_EMIT, then this function just counts the number
+// of bytes needed and returns NULL, and callers should not store any data
 uint8_t *mp_asm_base_get_cur_to_write_bytes(mp_asm_base_t *as, size_t num_bytes_to_write) {
-    if (as->pass < MP_ASM_PASS_EMIT) {
-        as->code_offset += num_bytes_to_write;
-        return as->dummy_data;
-    } else {
+    uint8_t *c = NULL;
+    if (as->pass == MP_ASM_PASS_EMIT) {
         assert(as->code_offset + num_bytes_to_write <= as->code_size);
-        uint8_t *c = as->code_base + as->code_offset;
-        as->code_offset += num_bytes_to_write;
-        return c;
+        c = as->code_base + as->code_offset;
     }
+    as->code_offset += num_bytes_to_write;
+    return c;
 }
 
 void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label) {
@@ -92,8 +91,7 @@ void mp_asm_base_align(mp_asm_base_t* as, unsigned int align) {
 // this function assumes a little endian machine
 void mp_asm_base_data(mp_asm_base_t* as, unsigned int bytesize, uintptr_t val) {
     uint8_t *c = mp_asm_base_get_cur_to_write_bytes(as, bytesize);
-    // only write to the buffer in the emit pass (otherwise we may overflow dummy_data)
-    if (as->pass == MP_ASM_PASS_EMIT) {
+    if (c != NULL) {
         for (unsigned int i = 0; i < bytesize; i++) {
             *c++ = val;
             val >>= 8;
diff --git a/py/asmbase.h b/py/asmbase.h
index 06fdd4b909a2e3808092e1ca56b30f26eb08bb76..d2b40389310edd6a2fe08025c6468af08e324fa1 100644
--- a/py/asmbase.h
+++ b/py/asmbase.h
@@ -40,9 +40,6 @@ typedef struct _mp_asm_base_t {
 
     size_t max_num_labels;
     size_t *label_offsets;
-
-    // must be last in struct
-    uint8_t dummy_data[4];
 } mp_asm_base_t;
 
 void mp_asm_base_init(mp_asm_base_t *as, size_t max_num_labels);
diff --git a/py/asmthumb.c b/py/asmthumb.c
index 82a226b62968d315a86d0c63e2376468e03b430e..749c1e405b99c3e8b9b16476afad5ff3b0521f53 100644
--- a/py/asmthumb.c
+++ b/py/asmthumb.c
@@ -162,18 +162,22 @@ STATIC mp_uint_t get_label_dest(asm_thumb_t *as, uint label) {
 
 void asm_thumb_op16(asm_thumb_t *as, uint op) {
     byte *c = asm_thumb_get_cur_to_write_bytes(as, 2);
-    // little endian
-    c[0] = op;
-    c[1] = op >> 8;
+    if (c != NULL) {
+        // little endian
+        c[0] = op;
+        c[1] = op >> 8;
+    }
 }
 
 void asm_thumb_op32(asm_thumb_t *as, uint op1, uint op2) {
     byte *c = asm_thumb_get_cur_to_write_bytes(as, 4);
-    // little endian, op1 then op2
-    c[0] = op1;
-    c[1] = op1 >> 8;
-    c[2] = op2;
-    c[3] = op2 >> 8;
+    if (c != NULL) {
+        // little endian, op1 then op2
+        c[0] = op1;
+        c[1] = op1 >> 8;
+        c[2] = op2;
+        c[3] = op2 >> 8;
+    }
 }
 
 #define OP_FORMAT_4(op, rlo_dest, rlo_src) ((op) | ((rlo_src) << 3) | (rlo_dest))
diff --git a/py/asmx64.c b/py/asmx64.c
index c9dad2a669ff2179aff4f1c39fb77214ae0a7f97..cf1a86b3f01b355600f7381aad7450aa57237bee 100644
--- a/py/asmx64.c
+++ b/py/asmx64.c
@@ -122,40 +122,50 @@ static inline byte *asm_x64_get_cur_to_write_bytes(asm_x64_t *as, int n) {
 
 STATIC void asm_x64_write_byte_1(asm_x64_t *as, byte b1) {
     byte* c = asm_x64_get_cur_to_write_bytes(as, 1);
-    c[0] = b1;
+    if (c != NULL) {
+        c[0] = b1;
+    }
 }
 
 STATIC void asm_x64_write_byte_2(asm_x64_t *as, byte b1, byte b2) {
     byte* c = asm_x64_get_cur_to_write_bytes(as, 2);
-    c[0] = b1;
-    c[1] = b2;
+    if (c != NULL) {
+        c[0] = b1;
+        c[1] = b2;
+    }
 }
 
 STATIC void asm_x64_write_byte_3(asm_x64_t *as, byte b1, byte b2, byte b3) {
     byte* c = asm_x64_get_cur_to_write_bytes(as, 3);
-    c[0] = b1;
-    c[1] = b2;
-    c[2] = b3;
+    if (c != NULL) {
+        c[0] = b1;
+        c[1] = b2;
+        c[2] = b3;
+    }
 }
 
 STATIC void asm_x64_write_word32(asm_x64_t *as, int w32) {
     byte* c = asm_x64_get_cur_to_write_bytes(as, 4);
-    c[0] = IMM32_L0(w32);
-    c[1] = IMM32_L1(w32);
-    c[2] = IMM32_L2(w32);
-    c[3] = IMM32_L3(w32);
+    if (c != NULL) {
+        c[0] = IMM32_L0(w32);
+        c[1] = IMM32_L1(w32);
+        c[2] = IMM32_L2(w32);
+        c[3] = IMM32_L3(w32);
+    }
 }
 
 STATIC void asm_x64_write_word64(asm_x64_t *as, int64_t w64) {
     byte* c = asm_x64_get_cur_to_write_bytes(as, 8);
-    c[0] = IMM32_L0(w64);
-    c[1] = IMM32_L1(w64);
-    c[2] = IMM32_L2(w64);
-    c[3] = IMM32_L3(w64);
-    c[4] = IMM64_L4(w64);
-    c[5] = IMM64_L5(w64);
-    c[6] = IMM64_L6(w64);
-    c[7] = IMM64_L7(w64);
+    if (c != NULL) {
+        c[0] = IMM32_L0(w64);
+        c[1] = IMM32_L1(w64);
+        c[2] = IMM32_L2(w64);
+        c[3] = IMM32_L3(w64);
+        c[4] = IMM64_L4(w64);
+        c[5] = IMM64_L5(w64);
+        c[6] = IMM64_L6(w64);
+        c[7] = IMM64_L7(w64);
+    }
 }
 
 /* unused
diff --git a/py/asmx64.h b/py/asmx64.h
index f80c8da8b204a347973577d7f408ef6d0f43f6d9..4499c53c327236adaaa1c0ab7e03ae990c33695b 100644
--- a/py/asmx64.h
+++ b/py/asmx64.h
@@ -72,7 +72,6 @@
 
 typedef struct _asm_x64_t {
     mp_asm_base_t base;
-    byte dummy_data[4]; // in addition to dummy_data in base
     int num_locals;
 } asm_x64_t;
 
diff --git a/py/asmx86.c b/py/asmx86.c
index cb9b30d402ffce5afa8f59b06dee86338b3cad90..ef315bf43a5c3cf610210ea0edc99ee4f8a40d77 100644
--- a/py/asmx86.c
+++ b/py/asmx86.c
@@ -101,29 +101,37 @@
 #define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)
 
 STATIC void asm_x86_write_byte_1(asm_x86_t *as, byte b1) {
-    byte* c = asm_x86_get_cur_to_write_bytes(as, 1);
-    c[0] = b1;
+    byte* c = mp_asm_base_get_cur_to_write_bytes(&as->base, 1);
+    if (c != NULL) {
+        c[0] = b1;
+    }
 }
 
 STATIC void asm_x86_write_byte_2(asm_x86_t *as, byte b1, byte b2) {
-    byte* c = asm_x86_get_cur_to_write_bytes(as, 2);
-    c[0] = b1;
-    c[1] = b2;
+    byte* c = mp_asm_base_get_cur_to_write_bytes(&as->base, 2);
+    if (c != NULL) {
+        c[0] = b1;
+        c[1] = b2;
+    }
 }
 
 STATIC void asm_x86_write_byte_3(asm_x86_t *as, byte b1, byte b2, byte b3) {
-    byte* c = asm_x86_get_cur_to_write_bytes(as, 3);
-    c[0] = b1;
-    c[1] = b2;
-    c[2] = b3;
+    byte* c = mp_asm_base_get_cur_to_write_bytes(&as->base, 3);
+    if (c != NULL) {
+        c[0] = b1;
+        c[1] = b2;
+        c[2] = b3;
+    }
 }
 
 STATIC void asm_x86_write_word32(asm_x86_t *as, int w32) {
-    byte* c = asm_x86_get_cur_to_write_bytes(as, 4);
-    c[0] = IMM32_L0(w32);
-    c[1] = IMM32_L1(w32);
-    c[2] = IMM32_L2(w32);
-    c[3] = IMM32_L3(w32);
+    byte* c = mp_asm_base_get_cur_to_write_bytes(&as->base, 4);
+    if (c != NULL) {
+        c[0] = IMM32_L0(w32);
+        c[1] = IMM32_L1(w32);
+        c[2] = IMM32_L2(w32);
+        c[3] = IMM32_L3(w32);
+    }
 }
 
 STATIC void asm_x86_write_r32_disp(asm_x86_t *as, int r32, int disp_r32, int disp_offset) {
diff --git a/py/asmx86.h b/py/asmx86.h
index ac4b2ecd087c1f262ec7240c427451cd07651242..0b44af6639bcf7e74d60241cc8b6c2946f5d827e 100644
--- a/py/asmx86.h
+++ b/py/asmx86.h
@@ -75,7 +75,6 @@
 
 typedef struct _asm_x86_t {
     mp_asm_base_t base;
-    byte dummy_data[4]; // in addition to dummy_data in base
     int num_locals;
 } asm_x86_t;
 
diff --git a/py/asmxtensa.c b/py/asmxtensa.c
index 00df432ce74982b38d3cd7f4e40cff909e89e1f5..00448dfc597d0c35be12b29599bcb747335226ee 100644
--- a/py/asmxtensa.c
+++ b/py/asmxtensa.c
@@ -97,15 +97,19 @@ STATIC uint32_t get_label_dest(asm_xtensa_t *as, uint label) {
 
 void asm_xtensa_op16(asm_xtensa_t *as, uint16_t op) {
     uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 2);
-    c[0] = op;
-    c[1] = op >> 8;
+    if (c != NULL) {
+        c[0] = op;
+        c[1] = op >> 8;
+    }
 }
 
 void asm_xtensa_op24(asm_xtensa_t *as, uint32_t op) {
     uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 3);
-    c[0] = op;
-    c[1] = op >> 8;
-    c[2] = op >> 16;
+    if (c != NULL) {
+        c[0] = op;
+        c[1] = op >> 8;
+        c[2] = op >> 16;
+    }
 }
 
 void asm_xtensa_j_label(asm_xtensa_t *as, uint label) {
@@ -147,7 +151,7 @@ void asm_xtensa_mov_reg_i32(asm_xtensa_t *as, uint reg_dest, uint32_t i32) {
         // load the constant
         asm_xtensa_op_l32r(as, reg_dest, as->base.code_offset, 4 + as->cur_const * WORD_SIZE);
         // store the constant in the table
-        if (as->base.pass == MP_ASM_PASS_EMIT) {
+        if (as->const_table != NULL) {
             as->const_table[as->cur_const] = i32;
         }
         ++as->cur_const;