diff --git a/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala b/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala
index f3a6bd72..9467d663 100644
--- a/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala
+++ b/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala
@@ -419,7 +419,7 @@ object AlwaysGoodI80Optimizations {
     },
     //20
     (Elidable & HasOpcode(PUSH) & HasRegisterParam(ZRegister.HL) & DoesntMatterWhatItDoesWith(ZRegister.DE)) ~
-      (Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer)).* ~
+      (Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer) & Not(Changes(DE))).* ~
       (Elidable & HasOpcode(POP) & HasRegisterParam(ZRegister.DE)) ~~> { code =>
       ZLine.ld8(ZRegister.D, ZRegister.H) ::
         ZLine.ld8(ZRegister.E, ZRegister.L) ::
@@ -427,7 +427,7 @@ object AlwaysGoodI80Optimizations {
     },
     //21
     (Elidable & HasOpcode(PUSH) & HasRegisterParam(ZRegister.HL) & DoesntMatterWhatItDoesWith(ZRegister.BC)) ~
-      (Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer)).* ~
+      (Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer) & Not(Changes(BC))).* ~
       (Elidable & HasOpcode(POP) & HasRegisterParam(ZRegister.BC)) ~~> { code =>
       ZLine.ld8(ZRegister.B, ZRegister.H) ::
         ZLine.ld8(ZRegister.C, ZRegister.L) ::
@@ -435,7 +435,7 @@ object AlwaysGoodI80Optimizations {
     },
     //22
     (Elidable & HasOpcode(PUSH) & HasRegisterParam(ZRegister.DE) & DoesntMatterWhatItDoesWith(ZRegister.HL)) ~
-      (Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer)).* ~
+      (Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer) & Not(Changes(HL))).* ~
       (Elidable & HasOpcode(POP) & HasRegisterParam(ZRegister.HL)) ~~> { code =>
       ZLine.ld8(ZRegister.H, ZRegister.D) ::
         ZLine.ld8(ZRegister.L, ZRegister.E) ::
@@ -443,7 +443,7 @@ object AlwaysGoodI80Optimizations {
     },
     //23
     (Elidable & HasOpcode(PUSH) & HasRegisterParam(ZRegister.BC) & DoesntMatterWhatItDoesWith(ZRegister.HL)) ~
-      (Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer)).* ~
+      (Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer) & Not(Changes(HL))).* ~
       (Elidable & HasOpcode(POP) & HasRegisterParam(ZRegister.HL)) ~~> { code =>
       ZLine.ld8(ZRegister.H, ZRegister.B) ::
         ZLine.ld8(ZRegister.L, ZRegister.C) ::
@@ -451,7 +451,7 @@ object AlwaysGoodI80Optimizations {
     },
     //24
     (Elidable & HasOpcode(PUSH) & HasRegisterParam(ZRegister.BC) & DoesntMatterWhatItDoesWith(ZRegister.DE)) ~
-      (Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer)).* ~
+      (Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer) & Not(Changes(DE))).* ~
       (Elidable & HasOpcode(POP) & HasRegisterParam(ZRegister.DE)) ~~> { code =>
       ZLine.ld8(ZRegister.D, ZRegister.B) ::
         ZLine.ld8(ZRegister.E, ZRegister.C) ::
@@ -459,7 +459,7 @@ object AlwaysGoodI80Optimizations {
     },
     //25
     (Elidable & HasOpcode(PUSH) & HasRegisterParam(ZRegister.DE) & DoesntMatterWhatItDoesWith(ZRegister.BC)) ~
-      (Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer)).* ~
+      (Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer) & Not(Changes(BC))).* ~
       (Elidable & HasOpcode(POP) & HasRegisterParam(ZRegister.BC)) ~~> { code =>
       ZLine.ld8(ZRegister.B, ZRegister.D) ::
         ZLine.ld8(ZRegister.C, ZRegister.E) ::
diff --git a/src/main/scala/millfork/compiler/AbstractStatementPreprocessor.scala b/src/main/scala/millfork/compiler/AbstractStatementPreprocessor.scala
index e2a638e8..bb833fd7 100644
--- a/src/main/scala/millfork/compiler/AbstractStatementPreprocessor.scala
+++ b/src/main/scala/millfork/compiler/AbstractStatementPreprocessor.scala
@@ -99,8 +99,10 @@ abstract class AbstractStatementPreprocessor(protected val ctx: CompilationConte
     }
     // generic warnings:
     stmt match {
-      case ExpressionStatement(expr@FunctionCallExpression("strzlen" | "putstrz" | "strzcmp" | "strzcopy", params)) =>
+      case ExpressionStatement(expr@FunctionCallExpression("strzlen" | "putstrz" | "strzcmp" | "strzcopy" | "strzpaste", params)) =>
         for (param <- params) checkIfNullTerminated(ctx, stmt, param)
+      case ExpressionStatement(expr@FunctionCallExpression("pstrlen" | "putpstr" | "pstrcmp" | "pstrcopy" | "pstrpaste", params)) =>
+        for (param <- params) checkIfLengthPrefixed(ctx, stmt, param)
 
       case ExpressionStatement(expr@FunctionCallExpression(f, List(VariableExpression(v)))) if hiddenEffectFreeFunctions(f)=>
         val volatile = ctx.env.maybeGet[ThingInMemory](v).fold(false)(_.isVolatile)
@@ -276,14 +278,34 @@ abstract class AbstractStatementPreprocessor(protected val ctx: CompilationConte
     val TERMINATOR = ctx.options.platform.defaultCodec.stringTerminator.head
     param match {
       case TextLiteralExpression(ch) =>
-        ch.last match {
-          case LiteralExpression(TERMINATOR, _) => //ok
+        ch.lastOption match {
+          case Some(LiteralExpression(TERMINATOR, _)) => //ok
           case _ => ctx.log.warn("Passing a non-null-terminated string to a function that expects a null-terminated string.", stmt.position)
         }
       case _ =>
     }
   }
 
+  private def checkIfLengthPrefixed(ctx: CompilationContext, stmt: ExecutableStatement, param: Expression): Unit = {
+    if (!ctx.options.flag(CompilationFlag.BuggyCodeWarning)) return
+    val TERMINATOR = ctx.options.platform.defaultCodec.stringTerminator.head
+    param match {
+      case TextLiteralExpression(ch) =>
+        if (ch.headOption match {
+          case Some(LiteralExpression(length, _)) if length == ch.size - 1 => false
+          case Some(LiteralExpression(length, _)) if length == ch.size + 2 =>
+            ch.lastOption match {
+              case Some(LiteralExpression(TERMINATOR, _)) => false
+              case _ => true
+            }
+          case _ => true
+        }) {
+          ctx.log.warn("Passing a non-length-prefixed string to a function that expects a length-prefixed string.", stmt.position)
+        }
+      case _ =>
+    }
+  }
+
   def search(expr: Expression, cv: VV): VV = {
     expr match {
       case FunctionCallExpression(op, List(VariableExpression(v), arg)) if op.endsWith("=") && op != "<=" && op != ">=" =>