program t36; { t36 -- every argument of a call keeps its own value. All three call parsers used to read the whole argument list first and emit the pushes afterwards: ParseCallArgs `p (a, b)' as a statement ParseCall a function call inside an expression IoCall write/read, one call per argument A computed argument (kind 2) has already been emitted and lives only in AX, so once the parser had moved on to the NEXT argument, AX belonged to whatever that argument computed and the earlier value was gone by the time the push loop reached it. TPSRC8 cproc/cprlp1 does it the other way round -- `CALL exprsave', then `CALL epushax', for each argument as it is parsed, and then a CALL, which is why the original cannot lose one. So: parse one argument, put it on the stack, parse the next. The callee follows the same ground truth from the other end (RESUME-TP3.md 3.11, and the Code Generation Internals stack frame): the LAST declared parameter is the one at BP+4, because the first declared is pushed first and so ends up farthest away. Every line below is derived by hand from the Pascal. The parameters are u, v, w in declaration order, and a=5, b=3, c=7, x=0 throughout, so each expected line can be written down without running anything: p3 (a, b, c) 5 3 7 three plain names: pins the three slots against either half of the convention being flipped alone p2 (x, a + b) 0 8 computed argument LAST p2 (a + b, x) 8 0 computed argument FIRST: the deferred push printed `0 0' here p3 (a+b, x, c*2) 8 0 14 two computed, one named p2 (add2 (a+b, 4), x) 12 0 a call nested in an argument b2 (a > b, x > c) TRUE FALSE boolean parameters, both computed write add2 (c*2, a) 19 a function call parsed by ParseCall write (b>a, ' ', x+1) FALSE 1 IoCall, two losses at once: deferred until the whole list had been read, the first argument was pushed as the THIRD argument's value (`TRUE') and the third was pushed after the earlier arguments' runtime calls had already had AX (`544' instead of 1) READ is not here on purpose: it refuses anything but a plain name, a name emits no code while it is parsed, and there is therefore nothing to lose. } var a : integer ; b : integer ; c : integer ; x : integer ; procedure p2 (u : integer, v : integer) ; begin writeln (u, ' ', v) end ; procedure p3 (u : integer, v : integer, w : integer) ; begin writeln (u, ' ', v, ' ', w) end ; procedure b2 (u : boolean, v : boolean) ; begin writeln (u, ' ', v) end ; function add2 (u : integer, v : integer) : integer ; begin add2 := u + v end ; begin a := 5 ; b := 3 ; c := 7 ; x := 0 ; p3 (a, b, c) ; p2 (x, a + b) ; p2 (a + b, x) ; p3 (a + b, x, c * 2) ; p2 (add2 (a + b, 4), x) ; b2 (a > b, x > c) ; writeln (add2 (c * 2, a)) ; writeln (b > a, ' ', x + 1) end.