ECHO OFF
setlocal
FOR /L %%A in (1,1,5) DO (
SET /a "B=%%A-1"
call ECHO %%B%%
)
Since you are not using setlocal, B will be set to the value from the previous run. %B% will be replaced by 4 since B was set to 4 by the previous run. the call echo trick uses a parsing quirk to retrieve the current (run-time) value of the variable.
Here's "the official" way:
ECHO OFF
setlocal enabledelayedexpansion
FOR /L %%A in (1,1,5) DO (
SET /a "B=%%A-1"
ECHO !B!
)
In delayedexpansion mode, !var! retrieves the value of var as it changes at run-time. This is not without its drawbacks, but you'd need to read up on delayedexpansion for a guide on that matter.