FOR OPERATOR: INTEL BRICKS

Back to:
index E97
I called bricks the short pieces of code, that "COMPAS" generate as a part of operator. Compiler builds result machine code from the bricks.

As it is clearly seen from logic of the structure, FOR construction consists from two blocks - before cycle body and after it.

Part before cycle body

Step 1 (extract value to begin cycle)

Step 2 (extract value to end cycle)

Step 3 (compare parameter's values and exit if incorrect)

Step 4 (store initial value into cycle variable)

Step 5 (save parameter address and last value)

Part after cycle body

Step 1 (restore parameter address and last value)

Step 2 (compare cycle parameter with end value, exit if equal)

Step 3 (make step)

Step 4 (go to repeat cycle)

And in the end example of full operator FOR


Before cycle: step 1 (extract value to begin cycle)

For this aim "COMPAS" uses standard bricks of assign operator, which extract value to AX.

Then "COMPAS" always moves this initial value into BX by simple command
89 C3 mov bx,ax



Back to:
index top E97

Before cycle: step 2 (extract value to end cycle)

For this aim "COMPAS" also uses standard bricks of assign operator, which extract value to AX. Now the first value is stored in BX and the last one - in AX.



Back to:
index top E97

Before cycle: step 3 (compare parameter's values and exit if incorrect)

To compare the initial value and the last one "COMPAS" generates the following instructions:
TO cycleDOWNTO cycle
39 C3cmp bx,ax 39 D8cmp ax,bx
7F ??jg ...(exit if > 0) 7F ??jg ...(exit if > 0)
Instead of ?? compiler will put the displacement to the first instruction after cycle.

As you can see from above, in both cases the cycle will be immediately finished if result > 0. Hence cycle with TO will be skipped if the initial value is greater than last one (BX > AX) and in the opposite case for DOWNTO cycle. So incorrect cycles
FOR i := 10 TO 1 DO and FOR i := 1 DOWNTO 10 DO
will be ignored. This check prevents possible endless cycle.



Back to:
index top E97

Before cycle: step 4 (store initial value into cycle variable)

This action is realized by the following commands:
BE {addr}mov si,{addr} move address of the cycle parameter to SI register
89 1Cmov [si],bx move initial value into variable
Instead of {addr} compiler will automatically place the address of the cycle variable.

I want to accent that now the last parameter value is still keeping in AX and SI stores the memory address of cycle variable. On the next step they will be saved in the stack.



Back to:
index top E97

Before cycle: step 5 (save parameter address and last value)

This is the last step before cycle body. Because we know exactly that the cycle contents will change AX and SI values, we must save them somewhere. "COMPAS" uses stack for this purpose and always generates here the following code:
50push ax
56push si

So the end parameter value (AX) and variable address (SI) is saved. After execution of the cycle body, these values will be restored by the first step.



Back to:
index top E97

[here must be the cycle body]


After cycle: step 1 (restore parameter address and last value)

This is the first step after cycle body execution. It restores the parameter address value in SI register and the end parameter value in AX. Note that the order of reading from stack is always opposite to writing one.
5Epop si
58pop ax



Back to:
index top E97

After cycle: step 2 (compare cycle parameter with end value, exit if equal)

To analyze the exit of the cycle, "COMPAS" generate constant code
3B 04cmp ax,[si] compare last parameter value with current one
74 07jz ... exit from the cycle when equal
Remember that [SI] points to stored in memory value of the variable, that is cycle parameter. The next instruction skips 7 bytes, where 2 last steps are placed. So when the current parameter value is identical to the end value, this instruction provides jump out of the cycle. (If no - the cycle continues to work and we go to the next step.)



Back to:
index top E97

After cycle: step 3 (make step)

The task of this step is to calculate next value for TO cycle and previous for DOWNTO
TODOWNTO
8B 0Cmov cx,[si] get variable value 8B 0Cmov cx,[si] get variable value
41inc cx inc variable value 49dec cx dec variable value
89 0Cmov [si],cx put variable value back 89 0Cmov cx,[si] put variable value back

You may be surprised, that this step contains 3 instructions (only one is needed for "E97"). But Intel processor has not inc [si] and dec [si] instructions...



Back to:
index top E97

After cycle: step 4 (go to repeat cycle)

This is just an unconditional brunch to repeat the cycle.
EB ??jmp ...
?? is a displacement, which will be calculated in every concrete case by "COMPAS".

It's important to note, that this is jump to step 5 before cycle, but not to beginning of the cycle body.



Back to:
index top E97

Example of full operator FOR

Here you can find full results of cycle FOR compilation.

FOR i:=9 DOWNTO 0 DO WRITELN(i);
(4FE - address of variable i)
AddrCodeOperationPascal commentsStep
280 B8 09 00
mov ax,9value to begin cycle step 1
283 89 C3 mov bx,axinitial cycle value to BX step 2
285 B8 00 00
mov ax,0value to end cycle (in AX)
288 39 D8 cmp ax,bxcompare first and last values step 3
28A 7F1D
jg 2A9 exit if incorrect values
28C BE FE 04
mov si,04FEaddress of cycle variable i step 4
28F 89 1C mov [si],bxassign initial value to i
291 50 push axsave last parameter value step 5
292 56 push sisave parameter address
293 A1 FE 04
mov ax,[4FE]variable i value cycle body
296 E8 BE FE
call 157call subroutine from RTL
(print integer value)
299 E8 F5 FE
call 191call subroutine from RTL
(to next display line)
29C 5E pop sirestore parameter address step 1
29D 58 pop axrestore last parameter value
29E 3B 04 cmp ax,[si]compare current value with end one step 2
2A0 74 07 jz 2A9exit if equal
2A2 8B 0C mov cx,[si] get parameter variable step 3
2A4 49 dec cx dec it
2A5 89 0C mov [si],cx put parameter variable back
2A7 EB E8 jmp 291to repeat cycle step 4
2A9 CD 20 INT 20quit to operating system



Back to:
index top E97