Oppolzer - Informatik / Stanford Pascal Compiler


Home       Lebenslauf       Schwerpunkte       Kenntnisse       Seminare       Kunden       Projekte       Produkte       Blog       Stanford Pascal       Kontakt

The Stanford Pascal Compiler / Evolution Steps

Back to Compiler main page

Verifying new P-Code instructions with the PCINT debugging features

Compiler version: 12.2017

To allow assignments of shorter string variables to longer string targets, I had to introduce a new P-Code instruction MFI (memory fill). I'd like to show you here, how the PCINT interpreter and its debugging features can be used to verify that new P-Code instructions are implemented correctly.

First of all, here is the Pascal example used:


program TESTSVAR ( OUTPUT ) ; type CHAR10 = array [ 1.. 10 ] of CHAR ; CHAR30 = array [ 1.. 30 ] of CHAR ; CHAR21 = array [ 20.. 40 ] of CHAR ; var F10 : CHAR10 ; F30 : CHAR30 ; F21 : CHAR21 ; begin (* HAUPTPROGRAMM *) F10 := 'Oppolzer' ; F30 := F10 ; WRITELN ( F30 ) ; F21 := 'Teststring Length 21' ; F30 := F21 ; WRITELN ( F30 ) ; F21 := F30 ; end (* HAUPTPROGRAMM *) .

You may notice that the assignments to F30 are ok, but the assignment to F21 is wrong, because F21 is shorter than F30. This is what the compiler says, too:


c:\work\pascal\work>pp testsvar PCINT (Build 1.0 Nov 11 2017 08:49:28) **** STANFORD PASCAL COMPILER, OPPOLZER VERSION OF 12.2017 **** 21 F21 := F30 ; ! +++ Error P129: TYPE CONFLICT OF OPERANDS **** Compiler Summary **** **** 1 Error. **** 22 LINE(S) READ, 0 PROCEDURE(S) COMPILED, **** 38 P_INSTRUCTIONS GENERATED, 0.05 SECONDS IN COMPILATION. **** Last Error/Warning on Line 21 **** Error/Warning Codes for this Program: **** P129: TYPE CONFLICT OF OPERANDS *** EXIT Aufruf mit Parameter = 1 ***

Luckily, the compiler simply omits the erroneous statement 21, so the resulting PRR file is usable, anyway. Here you can see the beginning of the PRR file:


c:\work\pascal\work>type testsvar.prr LOC 15 BGN TESTSVAR 10:31:22 11/12/2017 $PASMAIN ENT P,1,L3 $PASMAIN ,T,F,F,F,2,0,, LDA 1,352 LCA M,10,'Oppolzer ' MOV 10 LOC 16 LDA 1,362 LDA 1,352 DBG 1 LDC C,' ' MFI -30 MOV 10 LOC 17 ...

For debugging purposes, I generated the new DBG instruction just before the instruction sequence which sets up the MFI P-Code. DBG has no effect, if PCINT is started with debug=n, but with debug=y, the interpreter enters the debug dialog mode, when it encounters a DBG instruction. The operand on DBG currently has no meaning.

I now start the program using debug=y. The program (the PRR file) is translated into an internal memory representation and then executed, but, because the debug switch is on, execution stops at the very first P-Code instruction (which is BGN).


c:\work\pascal\work>pcint prr=testsvar.prr inc=paslibx,pasutils, pas=testsvar.pas out=testsvar.prrlis debug=y PCINT (Build 1.0 Nov 11 2017 08:49:28) ip=000001 sp=00000016 hp=02999984 00000000 00000000: 81818181 81818181 81818181 81818181 +................+ 00000016 00000010: 81818181 81818181 81818181 81818181 +................+ 000001: 007 0 1 BGN TESTSVAR 10:31:22 11/12/2017 g

The "g" command starts unlimited execution, but in this case execution stops, when the interpreter encounters the DBG instruction (in fact, after it processed the DBG instruction).


ip=000010 sp=00000024 hp=02999984 00000008 00000008: 81818181 81818181 81818181 6A010000 +............j...+ 00000024 00000018: 60010000 81818181 81818181 81818181 +................+ 00000040 00000028: 81818181 81818181 +........ + 000010: 041 C 0 32 LDC C,' ' asm

I switch to ASM mode using the "asm" command; in PAS mode, the debugger only stops once for every Pascal statement and not for every P-Code instruction.


*** Mode ASM set ip=000010 sp=00000024 hp=02999984 00000008 00000008: 81818181 81818181 81818181 6A010000 +............j...+ 00000024 00000018: 60010000 81818181 81818181 81818181 +................+ 00000040 00000028: 81818181 81818181 +........ + 000010: 041 C 0 32 LDC C,' ' s

Now I step one instruction forward using the "s" command.


ip=000011 sp=00000028 hp=02999984 00000012 0000000c: 81818181 81818181 6A010000 60010000 +........j.......+ 00000028 0000001c: 20000000 81818181 81818181 81818181 + ...............+ 00000044 0000002c: 81818181 81818181 81818181 +............ + 000011: 047 0 -30 MFI -30 d x16a x180

You may notice that the stack pointer SP has increased to 28; and the stack now contains the blank (X'20') at the topmost stack position. The address which will be the target of the subsequent MFI instruction is x0000016a (at the position sp - 8, little endian representation, because we are on a Windows machine). So I'd like to display the target area of the MFI instruction before executing it. This is what the "d" command does (from address ... to address, hex notation is possible).


00000362 0000016a: 81818181 81818181 81818181 81818181 +................+ 00000378 0000017a: 81818181 8181 +...... + ip=000011 sp=00000028 hp=02999984 00000012 0000000c: 81818181 81818181 6A010000 60010000 +........j.......+ 00000028 0000001c: 20000000 81818181 81818181 81818181 + ...............+ 00000044 0000002c: 81818181 81818181 81818181 +............ + 000011: 047 0 -30 MFI -30 s

The area (only 22 bytes are shown) is undefined; x'81' is the initialization pattern used by the runtime. So now I will execute the new implemented MFI instruction, to see, how it works ... using the "s" command.


ip=000012 sp=00000024 hp=02999984 00000008 00000008: 81818181 81818181 81818181 6A010000 +............j...+ 00000024 00000018: 60010000 20000000 81818181 81818181 +.... ...........+ 00000040 00000028: 81818181 81818181 +........ + 000012: 049 0 10 MOV 10 d x16a x180

Obviously, it popped one item from the stack, which is correct. Now let's see, if the area is filled correctly, by again displaying it.


00000362 0000016a: 20202020 20202020 20202020 20202020 + + 00000378 0000017a: 20202020 2020 + + ip=000012 sp=00000024 hp=02999984 00000008 00000008: 81818181 81818181 81818181 6A010000 +............j...+ 00000024 00000018: 60010000 20000000 81818181 81818181 +.... ...........+ 00000040 00000028: 81818181 81818181 +........ + 000012: 049 0 10 MOV 10 s

Looks good; now I execute the next instruction (MOV, using a length of 10).


ip=000013 sp=00000016 hp=02999984 00000000 00000000: 81818181 81818181 81818181 81818181 +................+ 00000016 00000010: 81818181 6A010000 60010000 20000000 +....j....... ...+ 000013: 044 0 17 LOC 17 *** LOC 17: WRITELN ( F30 ) ; g

The next instructions write the F30 buffer, so I will see the result anyway. I continue by using the "g" command.


Oppolzer ip=000030 sp=00000024 hp=02999984 00000008 00000008: 81818181 81818181 81818181 6A010000 +............j...+ 00000024 00000018: 88010000 1E000000 1E000000 81818181 +................+ 00000040 00000028: 81818181 81818181 +........ + 000030: 041 C 0 32 LDC C,' ' s ip=000031 sp=00000028 hp=02999984 00000012 0000000c: 81818181 81818181 6A010000 88010000 +........j.......+ 00000028 0000001c: 20000000 1E000000 81818181 81818181 + ...............+ 00000044 0000002c: 81818181 81818181 81818181 +............ + 000031: 047 0 -30 MFI -30 s ip=000032 sp=00000024 hp=02999984 00000008 00000008: 81818181 81818181 81818181 6A010000 +............j...+ 00000024 00000018: 88010000 20000000 1E000000 81818181 +.... ...........+ 00000040 00000028: 81818181 81818181 +........ + 000032: 049 0 21 MOV 21 s ip=000033 sp=00000016 hp=02999984 00000000 00000000: 81818181 81818181 81818181 81818181 +................+ 00000016 00000010: 81818181 6A010000 88010000 20000000 +....j....... ...+ 000033: 044 0 20 LOC 20 *** LOC 20: WRITELN ( F30 ) ; g

The content of F30 is shown correctly, as expected. Because there is another MFI in the code, execution stops again. I walk along the code using "s" commands (watch SP changing) and then use "g" to execute the rest of the program.


Teststring Length 21 c:\work\pascal\work>

This debug session proved IMO, that the new P-Code instruction works as desired. I finish by calling the program using debug=n; there should be no interruption.


c:\work\pascal\work>prun testsvar c:\work\pascal\work>pcint prr=testsvar.prr inc=paslibx,pasutils, pas=testsvar.pas out=testsvar.prrlis PCINT (Build 1.0 Nov 11 2017 08:49:28) Oppolzer Teststring Length 21 c:\work\pascal\work>

If you want to use the debug features of PCINT yourself, start it using debug=y and enter a question mark on the first prompt; you will get a short online help telling the available commands (at the moment in German, only ... sorry).

Warning: the actual version of PCINT may not work this way; you may have to wait for the 12.2017 version.

Back to Compiler main page