Proving Programs Correct

Similar documents
Lecture Notes: Hoare Logic

Hoare Logic: Proving Programs Correct

Review: Hoare Logic Rules

An Annotated Language

Chapter 3. Describing Syntax and Semantics ISBN

COMP 507: Computer-Aided Program Design

Softwaretechnik. Program verification. Albert-Ludwigs-Universität Freiburg. June 28, Softwaretechnik June 28, / 24

Softwaretechnik. Program verification. Software Engineering Albert-Ludwigs-University Freiburg. June 30, 2011

CSE 307: Principles of Programming Languages

Reasoning about programs

Last time. Reasoning about programs. Coming up. Project Final Presentations. This Thursday, Nov 30: 4 th in-class exercise

6. Hoare Logic and Weakest Preconditions

Semantics. There is no single widely acceptable notation or formalism for describing semantics Operational Semantics

Abstract Interpretation

Hoare Logic. COMP2600 Formal Methods for Software Engineering. Rajeev Goré

Lecture 5 - Axiomatic semantics

Lectures 20, 21: Axiomatic Semantics

Part II. Hoare Logic and Program Verification. Why specify programs? Specification and Verification. Code Verification. Why verify programs?

Formal Methods. CITS5501 Software Testing and Quality Assurance

AXIOMS OF AN IMPERATIVE LANGUAGE PARTIAL CORRECTNESS WEAK AND STRONG CONDITIONS. THE AXIOM FOR nop

Recap. Juan Pablo Galeotti,Alessandra Gorla, Software Engineering Chair Computer Science Saarland University, Germany

The 6502 Instruction Set

Main Goal. Language-independent program verification framework. Derive program properties from operational semantics

How to get an efficient yet verified arbitrary-precision integer library

Backward Reasoning: Rule for Assignment. Backward Reasoning: Rule for Sequence. Simple Example. Hoare Logic, continued Reasoning About Loops

Formal Systems Tutorial Hybrid System Modeling, Program Analysis

Axiomatic Semantics. More Semantics. Review - Operational Semantics. Partial Correctness Assertions. Programs Theorems. Axiomatic Semantics

Forward Assignment; Strongest Postconditions

III. Flags of the Processor Staus Register

Spring 2018 PhD Qualifying Exam in Languages

Axiomatic Semantics. Automated Deduction - George Necula - Lecture 2 1

No model may be available. Software Abstractions. Recap on Model Checking. Model Checking for SW Verif. More on the big picture. Abst -> MC -> Refine

4 bits Microcontroller

A Partial Correctness Proof for Programs with Decided Specifications

Guarded Commands, Nondeterminancy and Formal Derivation of Programs. Edsger W. Dijkstra. CACM 18, 8 pp (Aug. 1975).

COSC 243. Instruction Sets And Addressing Modes. Lecture 7&8 Instruction Sets and Addressing Modes. COSC 243 (Computer Architecture)

Program Static Analysis. Overview

Reasoning About Imperative Programs. COS 441 Slides 10

Introduction to Axiomatic Semantics

Overview. Verification with Functions and Pointers. IMP with assertions and assumptions. Proof rules for Assert and Assume. IMP+: IMP with functions

Harvard School of Engineering and Applied Sciences CS 152: Programming Languages

Hoare Logic and Model Checking

Hoare Logic and Model Checking. A proof system for Separation logic. Introduction. Separation Logic

Basic Verification Strategy

! Use of formal notations. ! in software system descriptions. ! for a broad range of effects. ! and varying levels of use. !

CS2104 Prog. Lang. Concepts

Chapter 3 (part 3) Describing Syntax and Semantics

The Rule of Constancy(Derived Frame Rule)

A short manual for the tool Accumulator

Verification Condition Generation via Theorem Proving

CITS5501 Software Testing and Quality Assurance Formal methods

CS158 Section B Exam 1 Key

Symbolic Execution and Proof of Properties

Verification Conditions. Juan Pablo Galeotti, Alessandra Gorla, Andreas Rau Saarland University, Germany

Axiomatic Rules. Lecture 18: Axiomatic Semantics & Type Safety. Correctness using Axioms & Rules. Axiomatic Rules. Steps in Proof

Shared Variables and Interference

Warm-Up Problem. 1. What is the definition of a Hoare triple satisfying partial correctness? 2. Recall the rule for assignment: x (assignment)

Deriving a Slicing Algorithm via FermaT Transformations

CIS 500 Software Foundations. Final Exam. May 3, Answer key

Formal Systems II: Applications

Programming Languages Third Edition

CIS 500: Software Foundations

Assertions & Verification & Example Loop Invariants Example Exam Questions

ABSTRACT ÅBO AKADEMI UNIVERSITY. Faculty of Mathematics and Natural Sciences. Department of Computer Science. Leonidas Tsiopoulos

Regarding the change of names mentioned in the document, such as Mitsubishi Electric and Mitsubishi XX, to Renesas Technology Corp.

Shared Variables and Interference

From Hoare Logic to Matching Logic Reachability. Grigore Rosu and Andrei Stefanescu University of Illinois, USA

Program Verification. Program Verification 307/434

Formal Verification of MIX Programs

4/24/18. Overview. Program Static Analysis. Has anyone done static analysis? What is static analysis? Why static analysis?

Lecture 10 Design by Contract

Assertions & Verification Example Exam Questions

CORRECTNESS ISSUES AND LOOP INVARIANTS

Hardware versus software

Mathematical Induction

From proposition to program

SECTION 1: CODE REASONING + VERSION CONTROL

Testing, Debugging, and Verification exam DIT082/TDA567. Day: 9 January 2016 Time: Will be published mid February or earlier

Introduction to Axiomatic Semantics (1/2)

MSO Lecture Design by Contract"

SECTION 1: CODE REASONING + VERSION CONTROL

COSC252: Programming Languages: Semantic Specification. Jeremy Bolton, PhD Adjunct Professor

Recall our recursive multiply algorithm:

REQUIREMENTS ANALYSIS. What versus how

PROPER TECHNIQUE OF SOFTWARE INSPECTION USING GUARDED COMMAND LANGUAGE

Exercise 3. Syntax Extensions. Reminder of the last lecture. This Lecture s Goals

How invariants help writing loops Author: Sander Kooijmans Document version: 1.0

Chapter 3. Describing Syntax and Semantics

Symbolic Execution and Verification Conditions. Review of Verification Conditions. Survey from Homework 4. Time spent: 7.1 hrs (mean), 6 hrs (median)

Formalizing Dijkstra

A Formal Basis For Removing Goto Statements

Combining Static and Dynamic Contract Checking for Curry

CMSC 330: Organization of Programming Languages

Chapter 3. Describing Syntax and Semantics

Verification Condition Generation

Programming Languages

Specifying and Verifying Programs (Part 2)

Formal Verification! Prof. Leon Osterweil! Computer Science 520/620! Spring 2011!

Slicing as a Program Transformation

SECTION 2: CODE REASONING + PROGRAMMING TOOLS. slides borrowed and adapted from Alex Mariakis and CSE 390a

Transcription:

Floyd-Hoare Logic: A formal system for proving correctness A program operates on state - moving through code changes state Hoare logic follows state changes through triples: {P } C {Q} where P is an assertion about the state before the execution of line C and Q is an assertion about the state after execution of C. Examples: {P } nop {P } {a == 1, a!= b} b := 2 {a == 1, a!= b} {??} a := b+1 {a > 1}

Floyd-Hoare Logic: A formal system for proving correctness A program operates on state - moving through code changes state Hoare logic follows state changes through triples: {P } C {Q} where P is an assertion about the state before the execution of line C and Q is an assertion about the state after execution of C. Examples: {P } nop {P } {a == 1, a!= b} b := 2 {a == 1, a!= b} {??} a := b+1 {a > 1} {b == 20} a := b+1 {a > 1} {b > 10} a := b+1 {a > 1} {b > 0} a := b+1 {a > 1} Weakest precondition

Floyd-Hoare Logic: A formal system for proving correctness A program operates on state - moving through code changes state Hoare logic follows state changes through triples: {P } C {Q} where P is an assertion about the state before the execution of line C and Q is an assertion about the state after execution of C. Examples: {P } nop {P } {a == 1, a!= b} b := 2 {a == 1, a!= b} {b > 10} a := b+1 {??}

Floyd-Hoare Logic: A formal system for proving correctness A program operates on state - moving through code changes state Hoare logic follows state changes through triples: {P } C {Q} where P is an assertion about the state before the execution of line C and Q is an assertion about the state after execution of C. Examples: {P } nop {P } {a == 1, a!= b} b := 2 {a == 1, a!= b} {b > 10} a := b+1 {??} {b > 10} a := b+1 {a > 0} {b > 10} a := b+1 {a > 11} Strongest postcondition

Floyd-Hoare Logic: A loop invariant: Used to prove loop properties. Assertions on state entering the loop and guaranteed to be true at every iteration of the loop. The invariant will be the postcondition for the loop on exit. Example: while (x < 10) x = x+1

Floyd-Hoare Logic: A loop invariant: Used to prove loop properties. Assertions on state entering the loop and guaranteed to be true at every iteration of the loop. The invariant will be the postcondition for the loop on exit. Example: while (x < 10) x = x+1 Start with this: {x <= 10} while (x < 10) x = x+1 {??}

Floyd-Hoare Logic: A loop invariant: Used to prove loop properties. Assertions on state entering the loop and guaranteed to be true at every iteration of the loop. The invariant will be the postcondition for the loop on exit. Example: while (x < 10) x = x+1 Start with this: {x <= 10} while (x < 10) x = x+1 {??} Move inside the test: {x < 10 x <= 10} x = x+1 {x <= 10}

Floyd-Hoare Logic: A loop invariant: Used to prove loop properties. Assertions on state entering the loop and guaranteed to be true at every iteration of the loop. The invariant will be the postcondition for the loop on exit. Example: while (x < 10) x = x+1 Start with this: {x <= 10} while (x < 10) x = x+1 {??} Move inside the test: {x < 10 x <= 10} x = x+1 {x <= 10} Backing out: {x < 10 x <= 10} while (x<10) x=x+1 { (x < 10) x <= 10}

Floyd-Hoare Logic Rules: Assignment: Let P[E/x] mean that in predicate P, expression E is substituted for symbol x where x is a free variable. {P[E/x]} x := E {P } Example: In {y == 10} x := y+1 {x == 11} P = {x == 11} E/x = (y +1)/x = {y+1} P[E/x] = {y+1 == 11} = {y == 10}

Floyd-Hoare Logic Rules: Composition: Example: {P } C 1 {Q}, {Q} C 2 {R} {P } C 1 ; C 2 {R} In {y == 10} x := y+1 {x == 11} and {x == 11} z := x+1 {z == 12} We can substitute {y == 10} x := y+1; z := x+1 {z == 12}

Floyd-Hoare Logic Rules: Condition: Example: In {A B} C 1 {Q}, { A B} C 2 {Q} {B} if A then C 1 else C 2 {Q} {a == T b == 6 c == 10} x := b {(x == 6 a == T) (x == 10 a == F)} and {a == F b == 6 c == 10} x := c {(x == 6 a == T) (x == 10 a == F)} After applying the condition rule: {(b == 6 c == 10)} If a == T then x := b; else x := c {(x == 6 a == T) (x == 10 a == F)}

Floyd-Hoare Logic Rules: Consequence: Example: Starting with: and P P, {P } C {Q}, Q Q {P } C {Q } {P } = {x +1 == 10} y := x +1 {y == 10} = {Q} P = (x == 9 x +1 == 10), Q = (x == 9 y == 10 y == 10), application of the consequence rule gives: {x == 9} y := x +1 {x == 9 y == 10}

Floyd-Hoare Logic Rules: While: Example: Starting with: {P A} C {P } {P } while A do C { A P } {x < 10 x <= 10} x = x +1; {x <= 10} After application of the while rule: {x <= 10} while(x < 10) x = x +1; { (x < 10) x <= 10} After application of the consequence rule: {x <= 10} while(x < 10) x = x +1; {x == 10}

Weakest Precondition: If Q is a predicate on states and C is a code fragment, then the weakest precondition for C with respect to Q is a predicate that is true for precisely those initial states in which C must terminate and must produce a state satisfying Q. Notation: wp(c, Q) - weakest precondition wrt Q, given code C. Example: {P } a := b +1 {a > 11} P = wp(a := b +1, a > 11) = b > 10 Nomenclature: wp is called a predicate transformer

Weakest Precondition: Example: {Q(y +3 z 5)} x := y +3 z 5 {Q(x)} Let v be the value assigned to x. If Q(x) is true after assignment so is Q(v) (before and after) Then Q(y +3 z 5) is true initially So, Q(x) holds after assignment iff Q(y +3 z 5) held Usefulness: Any predicate that implies wp(c,q) also implies Q Hence, if C is an entire program and Q specifies a property of C and if wp(c,q) is known to be the weakest precondition from the initial state, ACL2 can be used to determine input values that cause Q to be true.

Weakest Precondition: Proving Programs Correct 1. 2. 3. wp(c,q) State Space Q 1. from initial state to state not satisfying Q 2. from initial state to some state statisfying Q 3. from initial state to states statisfying Q

Strongest Postcondition: If P is a predicate on states and C is a code fragment, then the strongest postcondition for C with respect to P is a predicate that is implied by P when acted upon by C Notation: sp(c, P) - strongest postcondition wrt P, given code C. Example: {b > 10} a := b +1 {Q} Q = sp(a := b +1, b > 10) = a > 11 Nomenclature: sp is also called a predicate transformer

Predicate Transformers: PT semantics are a reformulation of Floyd-Hoare logic Used to implement an effective process for transforming F-H logic to predicate logic (so ACL2 can operate on it). WP - nop: wp(nop, Q) = Q WP - abort: wp(abort, Q) = false WP - assignment: wp(x := E, Q) = z.z == E Q[z/x] wp(x := E, Q) = Q[E/x] ex.: wp(x := x + 1, x > 10) = x + 1 > 10 x > 9

WP - composition: wp(c 1 ; C 2, Q) = wp(c 1,wp(C 2, Q)) ex.: wp(x := x +2;y := y 2, (x +y == 0)) = wp(x := x +2,wp(y := y 2, (x +y == 0))) = wp(x := x +2, (x + (y 2) == 0)) = ((x +2) +y 2) == 0 = x +y == 0 WP - condition: wp(if E then C 1 else C 2, Q) = (E wp(c 1, Q)) ( E wp(c 2, Q))) ex.: wp(if x > 2 then y := 1 else y := 1, (y > 0)) = ((x > 2) wp(y := 1, (y > 0))) ( (x > 2) wp(y := 1, (y > 0))) = ((x > 2) (1 > 0)) ( (x > 2) ( 1 > 0)) = ((x > 2) T) ( (x > 2) F)) = ((x > 2) T) ((x > 2) F)) = (x > 2)

WP - while: wp(while E do C, Q) = I y.((e I) wp(c, I (x < y)))[y/x] y.(( E I) Q)[y/x] invariant true before execution invariant and variant preserved Q holds on exit where < is well-founded, y represents the state before loop execution Alternatively, wp(while E do C, Q) = k. (k 0) P k P 0 = E Q and P k+1 = E wp(c, P k ) where Example: wp(while n > 0 do n := n 1, (n == 0)) P 0 = (n > 0) (n == 0) = (n == 0) P 1 = (n > 0) wp(n := n 1, (n == 0)) = (n == 1) P 2 = (n > 0) wp(n := n 1, (n == 1)) = (n == 2)... k. (k 0) P k = (n >= 0).

Example: wp(while n! = 0 do n := n 1, (n == 0)) P 0 = (n! = 0) (n == 0) = (n == 0) P 1 = (n! = 0) wp(n := n 1, (n == 0)) = (n == 1) P 2 = (n! = 0) wp(n := n 1, (n == 1)) = (n == 2)... k. (k 0) P k = (n >= 0).

Example: 1 + 3 + 5... + n = ((n + 1)/2) 2 n. (n 1) n i=1 (2 i 1) = n2 A program for implementing this: {(n >= 0)} i := 0; s := 0; while i!= n do i := i+1; s := s + (2*i - 1); {(s == n*n)} P 0 = ((i == n) (s == n n)) P 1 = ((i == n 1) (s == i i)) P 2 = ((i == n 2) (s == i i))... P j = ((i == n j) (s == i i)) wp(while..., (s == n n)) = ((i <= n) (s == i i)) wp(i := 0;s := 0, ((i <= n) (s == i i)) = ((0 <= n) (s == 0))

Computing P 1 : P 1 = (i! = n) wp(i := i +1; s := s +2 1 1, ((i == n) (s == n n)) = (i! = n) wp(i := i +1, ((i == n) (s +2 i 1 == n n)) = (i! = n) wp(i := i +1, ((i == n) (s == (i 1) (i 1)) = (i! = n) (i +1 == n) (s == (i +1 1) (i +1 1))

Useful special cases: wp(c, Q) = T wp(c, T) = T wp(c, Q) = F wp(c, T) = F C terminates with Q from any initial state C terminates from any initial state C produces a state where Q is false from any initial state that results in C terminating C does not terminate from any initial state Other properties: {wp(c, Q)} C {Q} wp(c, F) = F wp(c, Q R) = (wp(c, Q) wp(c, R)) if Q R then wp(c, Q) wp(c, R)

A multiply program: Proving Programs Correct { F1=F1SAVE & F1<2**bits & F2<2**bits & LOW<2**bits } LDX #bits load the X register immediate with number bits LDA #0 load the A register immediate with the value 0 LOOP ROR F1 rotate F1 right circular through the carry flag BCC ZCOEF branch on carry flag clear to ZCOEF CLC clear the carry flag ADC F2 add with carry F2 to the contents of A ZCOEF ROR A rotate A right circular through the carry flag ROR LOW rotate LOW right circular through the carry flag DEX decrement the X register by 1 BNE LOOP branch if X is non-zero to LOOP { LOW + 2**bits*A = F1SAVE*F2 } A is an 8 bit accumulator - for the high bits of the multiply LOW is an 8 bit accumulator - for the low bits of the multiply Right rotation of A and then LOW is a 16 bit right rotation through both There are Z and C bits, and registers X, F1, F2 ADC adds F2 and the C bit to A

Setup weakest preconditions: { F1=F1SAVE & F1<256 & F2<256 & LOW<256 } LDX #bits S 1 [8/X]S 2 () LDA #0 S 2 [0/A]S 3 () LOOP ROR F1 S 3 [E 4 /F1, E 8 /C]S 4 () BCC ZCOEF S 4 if C == 0 S 5 () else S 7 () CLC S 5 [0/C]S 6 () ADC F2 S 6 [E 3 /A, E 7 /C, E 9 /Z]S 7 () ZCOEF ROR A S 7 [E 2 /A, E 6 /C]S 8 () ROR LOW S 8 [E 1 /LOW, E 5 /C]S 9 (X,LOW,C) DEX S 9 (X,LOW,C) [X 1/X]S 10 (X,LOW,C) BNE LOOP S 10 (X) if Z==0 S 3 () else {LOW+256*A == F1SAVE*F2} Q = { LOW + 256*A = F1SAVE*F2 } E 1 : LOW/2 + C*128 E 5 : LOW mod 2 E 2 : A/2 + C*128 E 6 : A mod 2 E 3 : A+F2+C mod 256 E 7 : (A+F2+C)/256 E 4 : F1/2 + C*128 E 8 : F1 mod 2 E 9 : A+F2+C mod 256 == 0

Collapse non-branching instructions: { F1=F1SAVE & F1<256 & F2<256 & LOW<256 } LDX #bits S 1 [8/X, 0/A]S 3 () LDA #0 LOOP ROR F1 S 3 [E 4 /F1, E 8 /C]S 4 () BCC ZCOEF S 4 if C == 0 S 5 () else S 7 () CLC S 5 [0/C]S 6 () ADC F2 S 6 [E 3 /A, E 7 /C, E 9 /Z]S 7 () ZCOEF ROR A S 7 [E 2 /A, E 6 /C]S 8 () ROR LOW S 8 [E 1 /LOW, E 5 /C]S 9 (X,LOW,C) DEX S 9 (X,LOW,C) [X 1/X]S 10 (X,LOW,C) BNE LOOP S 10 (X) if Z==0 S 3 () else {LOW+256*A == F1SAVE*F2} Q = { LOW + 256*A = F1SAVE*F2 } E 1 : LOW/2 + C*128 E 5 : LOW mod 2 E 2 : A/2 + C*128 E 6 : A mod 2 E 3 : A+F2+C mod 256 E 7 : (A+F2+C)/256 E 4 : F1/2 + C*128 E 8 : F1 mod 2 E 9 : A+F2+C mod 256 == 0

Collapse non-branching instructions: { F1=F1SAVE & F1<256 & F2<256 & LOW<256 } LDX #bits S 1 [8/X, 0/A]S 3 () LDA #0 LOOP ROR F1 S 3 [E 4 /F1, E 8 /C]S 4 () BCC ZCOEF S 4 if C == 0 S 5 () else S 7 () CLC S 5 [0/C]S 6 () ADC F2 S 6 [E 3 /A, E 7 /C, E 9 /Z]S 7 () ZCOEF ROR A S 7 [E 2 /A, E 6 /C]S 8 () ROR LOW S 8 [E 1 /LOW, E 5 /C,X 1/X]S 10 (X,LOW,C) DEX BNE LOOP S 10 (X) if Z==0 S 3 () else {LOW+256*A == F1SAVE*F2} Q = { LOW + 256*A = F1SAVE*F2 } E 1 : LOW/2 + C*128 E 5 : LOW mod 2 E 2 : A/2 + C*128 E 6 : A mod 2 E 3 : A+F2+C mod 256 E 7 : (A+F2+C)/256 E 4 : F1/2 + C*128 E 8 : F1 mod 2 E 9 : A+F2+C mod 256 == 0

Collapse non-branching instructions: { F1=F1SAVE & F1<256 & F2<256 & LOW<256 } LDX #bits S 1 [8/X, 0/A]S 3 () LDA #0 LOOP ROR F1 S 3 [E 4 /F1, E 8 /C]S 4 () BCC ZCOEF S 4 if C == 0 S 5 () else S 7 () CLC S 5 [0/C]S 6 () ADC F2 S 6 [E 3 /A, E 7 /C, E 9 /Z]S 7 () ZCOEF ROR A S 7 [E 2 /A, E 6 /C, E 1 /LOW,X 1/X]S 10 () ROR LOW DEX BNE LOOP S 10 (X) if Z==0 S 3 () else {LOW+256*A == F1SAVE*F2} Q = { LOW + 256*A = F1SAVE*F2 } E 1 : LOW/2 + C*128 E 5 : LOW mod 2 E 2 : A/2 + C*128 E 6 : A mod 2 E 3 : A+F2+C mod 256 E 7 : (A+F2+C)/256 E 4 : F1/2 + C*128 E 8 : F1 mod 2 E 9 : A+F2+C mod 256 == 0

Collapse non-branching instructions: { F1=F1SAVE & F1<256 & F2<256 & LOW<256 } LDX #bits S 1 [8/X, 0/A]S 3 () LDA #0 LOOP ROR F1 S 3 [E 4 /F1, E 8 /C]S 4 () BCC ZCOEF S 4 if C == 0 S 5 () else S 7 () CLC S 5 [0/C, E 3 /A, E 7 /C, E 9 /Z]S 7 () ADC F2 ZCOEF ROR A S 7 [E 2 /A, E 6 /C, E 1 /LOW,X 1/X]S 10 () ROR LOW DEX BNE LOOP S 10 (X) if Z==0 S 3 () else {LOW+256*A == F1SAVE*F2} Q = { LOW + 256*A = F1SAVE*F2 } E 1 : LOW/2 + C*128 E 5 : LOW mod 2 E 2 : A/2 + C*128 E 6 : A mod 2 E 3 : A+F2+C mod 256 E 7 : (A+F2+C)/256 E 4 : F1/2 + C*128 E 8 : F1 mod 2 E 9 : A+F2+C mod 256 == 0

Put conditionals in proper form: { F1=F1SAVE & F1<256 & F2<256 & LOW<256 } LDX #bits S 1 [8/X, 0/A]S 3 () LDA #0 LOOP ROR F1 S 3 [E 4 /F1, E 8 /C]S 4 () BCC ZCOEF S 4 if C == 0 S 5 () else S 7 () CLC S 5 [0/C, E 3 /A, E 7 /C, E 9 /Z]S 7 () ADC F2 ZCOEF ROR A S 7 [E 2 /A, E 6 /C, E 1 /LOW,X 1/X]S 10 () ROR LOW DEX BNE LOOP S 10 (X) ( Z S 3 ()) (Z {LOW +256 A == F1SAVE F2}) Q = { LOW + 256*A = F1SAVE*F2 } E 1 : LOW/2 + C*128 E 5 : LOW mod 2 E 2 : A/2 + C*128 E 6 : A mod 2 E 3 : A+F2+C mod 256 E 7 : (A+F2+C)/256 E 4 : F1/2 + C*128 E 8 : F1 mod 2 E 9 : A+F2+C mod 256 == 0

Put conditionals in proper form: { F1=F1SAVE & F1<256 & F2<256 & LOW<256 } LDX #bits S 1 [8/X, 0/A]S 3 () LDA #0 LOOP ROR F1 S 3 [E 4 /F1, E 8 /C]S 4 () BCC ZCOEF S 4 ( C S 5 ()) (C S 7 ()) CLC S 5 [0/C, E 3 /A, E 7 /C, E 9 /Z]S 7 () ADC F2 ZCOEF ROR A S 7 [E 2 /A, E 6 /C, E 1 /LOW,X 1/X]S 10 () ROR LOW DEX BNE LOOP S 10 (X) ( Z S 3 ()) (Z {LOW +256 A == F1SAVE F2}) Q = { LOW + 256*A = F1SAVE*F2 } E 1 : LOW/2 + C*128 E 5 : LOW mod 2 E 2 : A/2 + C*128 E 6 : A mod 2 E 3 : A+F2+C mod 256 E 7 : (A+F2+C)/256 E 4 : F1/2 + C*128 E 8 : F1 mod 2 E 9 : A+F2+C mod 256 == 0

Create recursive functions representing weakest preconditions: S 7 [E 2 /A, E 6 /C, E 1 /LOW,X 1/X]S 10

Create recursive functions representing weakest preconditions: S 7 [E 2 /A, E 6 /C, E 1 /LOW,X 1/X]( ( Z S 3 ) (Z {LOW +256 A = F1SAVE F2}))

Create recursive functions representing weakest preconditions: S 7 [E 2 /A, E 6 /C, E 1 /LOW,X 1/X]( ( Z [E 4 /F1, E 8 /C](( C S 5 ) (C S 7 ))) (Z {LOW +256 A = F1SAVE F2}))

Create recursive functions representing weakest preconditions: S 7 [E 2 /A, E 6 /C, E 1 /LOW,X 1/X]( ( Z [E 4 /F1, E 8 /C]( ( C [0/C, E 3 /A, E 7 /C, E 9 /Z]S 7 ) (C S 7 ))) (Z {LOW +256 A = F1SAVE F2}))

Create recursive functions representing weakest preconditions: S 7 [E 2 /A, E 6 /C, E 1 /LOW,X 1/X]( ( Z [E 4 /F1, E 8 /C]( ( C [0/C, E 3 /A, E 7 /C, E 9 /Z]S 7 ) (C S 7 ))) (Z {LOW +256 A = F1SAVE F2})) (DEFUN WP-ZCOEF (F1 C LOW A F1SAVE F2 X) (IF (EQUAL (DEC X) 0) (EQUAL (+ (* (+ (* C 128) (FLOOR A 2)) 256) (+ (* (MOD A 2) 128) (FLOOR LOW 2))) (* F1SAVE F2)) (WP-ZCOEF (+ (* (MOD LOW 2) 128) (FLOOR F1 2)) (* (MOD F1 2) (FLOOR (+ (+ (* C 128) (FLOOR A 2)) F2) 256)) (+ (* (MOD A 2) 128) (FLOOR LOW 2)) (+ (* (- 1 (MOD F1 2)) (+ (* C 128) (FLOOR A 2))) (* (MOD F1 2) (MOD (+ (+ (* C 128) (FLOOR A 2)) F2) 256))) F1SAVE F2 (DEC X))))