diff --git a/src/main/scala/millfork/Main.scala b/src/main/scala/millfork/Main.scala
index 13f5235c..21edf0ab 100644
--- a/src/main/scala/millfork/Main.scala
+++ b/src/main/scala/millfork/Main.scala
@@ -102,7 +102,7 @@ object Main {
     ErrorReporting.debug(f"Unoptimized code size: ${assembler.unoptimizedCodeSize}%5d B")
     ErrorReporting.debug(f"Optimized code size:   ${assembler.optimizedCodeSize}%5d B")
     ErrorReporting.debug(f"Gain:                   ${(100L * (assembler.unoptimizedCodeSize - assembler.optimizedCodeSize) / assembler.unoptimizedCodeSize.toDouble).round}%5d%%")
-    ErrorReporting.debug(f"Initialized arrays:    ${assembler.initializedArraysSize}%5d B")
+    ErrorReporting.debug(f"Initialized variables: ${assembler.initializedVariablesSize}%5d B")
 
     if (c.outputAssembly) {
       val path = Paths.get(assOutput)
diff --git a/src/main/scala/millfork/env/Environment.scala b/src/main/scala/millfork/env/Environment.scala
index c5d8cb2b..776a850a 100644
--- a/src/main/scala/millfork/env/Environment.scala
+++ b/src/main/scala/millfork/env/Environment.scala
@@ -54,9 +54,10 @@ class Environment(val parent: Option[Environment], val prefix: String) {
     case _ => None
   }.toList
 
-  def allPreallocatables: List[PrellocableThing] = things.values.flatMap {
+  def allPreallocatables: List[PreallocableThing] = things.values.flatMap {
     case m: NormalFunction => Some(m)
     case m: InitializedArray => Some(m)
+    case m: InitializedMemoryVariable => Some(m)
     case _ => None
   }.toList
 
@@ -413,7 +414,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
     stmt.assemblyParamPassingConvention match {
       case ByVariable(name) =>
         val zp = typ.name == "pointer" // TODO
-      val v = MemoryVariable(prefix + name, typ, if (zp) VariableAllocationMethod.Zeropage else VariableAllocationMethod.Auto)
+      val v = UninitializedMemoryVariable(prefix + name, typ, if (zp) VariableAllocationMethod.Zeropage else VariableAllocationMethod.Auto)
         addThing(v, stmt.position)
         registerAddressConstant(v, stmt.position)
         if (typ.size == 2) {
@@ -452,7 +453,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
                   case Some(aa) => RelativeArray(stmt.name + ".array", aa, length.toInt)
                 }
                 addThing(array, stmt.position)
-                registerAddressConstant(MemoryVariable(stmt.name, p, VariableAllocationMethod.None), stmt.position)
+                registerAddressConstant(UninitializedMemoryVariable(stmt.name, p, VariableAllocationMethod.None), stmt.position)
                 val a = address match {
                   case None => array.toAddress
                   case Some(aa) => aa
@@ -486,7 +487,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
         val data = contents.map(x => eval(x).getOrElse(Constant.error(s"Array `${stmt.name}` has non-constant contents", stmt.position)))
         val array = InitializedArray(stmt.name + ".array", address, data)
         addThing(array, stmt.position)
-        registerAddressConstant(MemoryVariable(stmt.name, p, VariableAllocationMethod.None), stmt.position)
+        registerAddressConstant(UninitializedMemoryVariable(stmt.name, p, VariableAllocationMethod.None), stmt.position)
         val a = address match {
           case None => array.toAddress
           case Some(aa) => aa
@@ -538,7 +539,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
       }
     } else {
       if (stmt.stack && stmt.global) ErrorReporting.error(s"`$name` is static or global and cannot be on stack", position)
-      if (stmt.initialValue.isDefined) ErrorReporting.error(s"`$name` is not a constant and cannot have a value", position)
+      if (stmt.initialValue.isDefined && parent.isDefined) ErrorReporting.error(s"`$name` is local and not a constant and therefore cannot have a value", position)
       if (stmt.stack) {
         val v = StackVariable(prefix + name, typ, this.baseStackOffset)
         baseStackOffset += typ.size
@@ -550,7 +551,16 @@ class Environment(val parent: Option[Environment], val prefix: String) {
       } else {
         val (v, addr) = stmt.address.fold[(VariableInMemory, Constant)]({
           val alloc = if (typ.name == "pointer") VariableAllocationMethod.Zeropage else if (stmt.global) VariableAllocationMethod.Static else VariableAllocationMethod.Auto
-          val v = MemoryVariable(prefix + name, typ, alloc)
+          if (alloc != VariableAllocationMethod.Static && stmt.initialValue.isDefined) {
+            ErrorReporting.error(s"`$name` cannot be preinitialized`", position)
+          }
+          val v = stmt.initialValue.fold[MemoryVariable](UninitializedMemoryVariable(prefix + name, typ, alloc)){ive =>
+            if (options.flags(CompilationFlag.ReadOnlyArrays)) {
+              ErrorReporting.warn("Initialized variable in read-only segment", options, position)
+            }
+            val ivc = eval(ive).getOrElse(Constant.error(s"Initial value of `$name` is not a constant", position))
+            InitializedMemoryVariable(name, None, typ, ivc)
+          }
           registerAddressConstant(v, stmt.position)
           (v, v.toAddress)
         })(a => {
diff --git a/src/main/scala/millfork/env/Thing.scala b/src/main/scala/millfork/env/Thing.scala
index 38d13035..4ab982c1 100644
--- a/src/main/scala/millfork/env/Thing.scala
+++ b/src/main/scala/millfork/env/Thing.scala
@@ -75,7 +75,7 @@ sealed trait ThingInMemory extends Thing {
   def toAddress: Constant
 }
 
-sealed trait PrellocableThing extends ThingInMemory {
+sealed trait PreallocableThing extends ThingInMemory {
   def shouldGenerate: Boolean
 
   def address: Option[Constant]
@@ -118,7 +118,15 @@ case class StackVariable(name: String, typ: Type, baseOffset: Int) extends Varia
   def sizeInBytes: Int = typ.size
 }
 
-case class MemoryVariable(name: String, typ: Type, alloc: VariableAllocationMethod.Value) extends VariableInMemory with UninitializedMemory {
+object MemoryVariable {
+  def unapply(v: MemoryVariable) = Some((v.name, v.typ, v.alloc))
+}
+
+abstract class MemoryVariable extends VariableInMemory {
+  def alloc: VariableAllocationMethod.Value
+}
+
+case class UninitializedMemoryVariable(name: String, typ: Type, alloc: VariableAllocationMethod.Value) extends MemoryVariable with UninitializedMemory {
   override def sizeInBytes: Int = typ.size
 
   override def zeropage: Boolean = alloc == VariableAllocationMethod.Zeropage
@@ -126,6 +134,16 @@ case class MemoryVariable(name: String, typ: Type, alloc: VariableAllocationMeth
   override def toAddress: MemoryAddressConstant = MemoryAddressConstant(this)
 }
 
+case class InitializedMemoryVariable(name: String, address: Option[Constant], typ: Type, initialValue: Constant) extends MemoryVariable with PreallocableThing {
+  override def zeropage: Boolean = false
+
+  override def toAddress: MemoryAddressConstant = MemoryAddressConstant(this)
+
+  override def shouldGenerate: Boolean = true
+
+  override def alloc: VariableAllocationMethod.Value = VariableAllocationMethod.Static
+}
+
 trait MlArray extends ThingInMemory
 
 case class UninitializedArray(name: String, sizeInBytes: Int) extends MlArray with UninitializedMemory {
@@ -138,7 +156,7 @@ case class RelativeArray(name: String, address: Constant, sizeInBytes: Int) exte
   override def toAddress: Constant = address
 }
 
-case class InitializedArray(name: String, address: Option[Constant], contents: List[Constant]) extends MlArray with PrellocableThing {
+case class InitializedArray(name: String, address: Option[Constant], contents: List[Constant]) extends MlArray with PreallocableThing {
   override def shouldGenerate = true
 }
 
@@ -196,7 +214,7 @@ case class NormalFunction(name: String,
                           code: List[ExecutableStatement],
                           interrupt: Boolean,
                           reentrant: Boolean,
-                          position: Option[Position]) extends FunctionInMemory with PrellocableThing {
+                          position: Option[Position]) extends FunctionInMemory with PreallocableThing {
   override def shouldGenerate = true
 }
 
diff --git a/src/main/scala/millfork/output/Assembler.scala b/src/main/scala/millfork/output/Assembler.scala
index d4f06231..42183256 100644
--- a/src/main/scala/millfork/output/Assembler.scala
+++ b/src/main/scala/millfork/output/Assembler.scala
@@ -21,7 +21,7 @@ class Assembler(private val rootEnv: Environment) {
   var env = rootEnv.allThings
   var unoptimizedCodeSize = 0
   var optimizedCodeSize = 0
-  var initializedArraysSize = 0
+  var initializedVariablesSize = 0
 
   val mem = new CompiledMemory
   val labelMap = mutable.Map[String, Int]()
@@ -154,7 +154,7 @@ class Assembler(private val rootEnv: Environment) {
           mem.banks(0).writeable(index) = true
           index += 1
         }
-        initializedArraysSize += items.length
+        initializedVariablesSize += items.length
       case InitializedArray(name, Some(_), items) => ???
       case f: NormalFunction if f.address.isDefined =>
         var index = f.address.get.asInstanceOf[NumericConstant].value.toInt
@@ -187,7 +187,23 @@ class Assembler(private val rootEnv: Environment) {
           mem.banks(0).writeable(index) = true
           index += 1
         }
-        initializedArraysSize += items.length
+        initializedVariablesSize += items.length
+      case m@InitializedMemoryVariable(name, None, typ, value) =>
+        if (options.flags(CompilationFlag.PreventJmpIndirectBug) && (index & 0xff) + typ.size > 0x100) {
+          index = (index & 0xffff00) + 0x100
+        }
+        labelMap(name) = index
+        val altName = m.name.stripPrefix(env.prefix) + "`"
+        env.things += altName -> ConstantThing(altName, NumericConstant(index, 2), env.get[Type]("pointer"))
+        assembly.append("* = $" + index.toHexString)
+        assembly.append(name)
+        for(i <- 0 until typ.size) {
+          writeByte(0, index, value.subbyte(i))
+          assembly.append("    !byte " + value.subbyte(i).quickSimplify)
+          mem.banks(0).writeable(index) = true
+          index += 1
+        }
+        initializedVariablesSize += typ.size
       case _ =>
     }
     val allocator = platform.allocator
diff --git a/src/test/scala/millfork/test/BasicSymonTest.scala b/src/test/scala/millfork/test/BasicSymonTest.scala
index ddf0f6a3..e34b7441 100644
--- a/src/test/scala/millfork/test/BasicSymonTest.scala
+++ b/src/test/scala/millfork/test/BasicSymonTest.scala
@@ -25,4 +25,31 @@ class BasicSymonTest extends FunSuite with Matchers {
         | }
       """.stripMargin).readByte(0xc000) should equal(1)
   }
+
+  test("Preallocated variables") {
+    val m = EmuUnoptimizedRun(
+      """
+        | array output [2] @$c000
+        | byte number = 4
+        | void main () {
+        |  output[0] = number
+        |  number += 1
+        |  output[1] = number
+        | }
+      """.stripMargin)
+      m.readByte(0xc000) should equal(4)
+      m.readByte(0xc001) should equal(5)
+  }
+
+  test("Preallocated variables 2") {
+    val m = EmuUnoptimizedRun(
+      """
+        | word output @$c000
+        | word number = 344
+        | void main () {
+        |  output = number
+        | }
+      """.stripMargin)
+      m.readWord(0xc000) should equal(344)
+  }
 }
diff --git a/src/test/scala/millfork/test/emu/EmuRun.scala b/src/test/scala/millfork/test/emu/EmuRun.scala
index 59b0c853..19d79c82 100644
--- a/src/test/scala/millfork/test/emu/EmuRun.scala
+++ b/src/test/scala/millfork/test/emu/EmuRun.scala
@@ -6,7 +6,7 @@ import com.loomcom.symon.{Bus, Cpu, CpuState}
 import fastparse.core.Parsed.{Failure, Success}
 import millfork.assembly.opt.AssemblyOptimization
 import millfork.compiler.{CompilationContext, MlCompiler}
-import millfork.env.{Environment, InitializedArray, NormalFunction}
+import millfork.env.{Environment, InitializedArray, InitializedMemoryVariable, NormalFunction}
 import millfork.error.ErrorReporting
 import millfork.node.StandardCallGraph
 import millfork.node.opt.NodeOptimization
@@ -134,6 +134,11 @@ class EmuRun(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimization],
             d.contents.foreach(c => println("    !byte " + c))
             unoptimizedSize += d.contents.length
             optimizedSize += d.contents.length
+          case d: InitializedMemoryVariable =>
+            println(d.name)
+            0.until(d.typ.size).foreach(c => println("    !byte " + d.initialValue.subbyte(c)))
+            unoptimizedSize += d.typ.size
+            optimizedSize += d.typ.size
         }
 
         ErrorReporting.assertNoErrors("Compile failed")