In the example for the move generation of white pawns we advanced all pawns one rank and filtered out those pawns reaching the 8th rank and those hitting another piece. The result was a BitBoard with valid target squares for simple pawn moves.
In order to make use of that result we must now translate the set bit positions back into squares. The naive way is just looping through the bitboard and looking at each single bit whether it is 1.
bb : BitBoard;
i : integer;
while (pos<=63) and ((bb AND (2^pos))<>0) do inc(pos);
if pos<64 then ...
This finds the least significant bit in bb. You can now do something with this information. Then you delete this bit in bb via bb := bb and NOT (2^pos) and start over again to find the next bit until bb is 0. Then all bits are processed.
This works but is slow. As finding a bit in a BitBoard is called millions of times during search for a best move you want that operation to be very fast. So this is not a reasonable approach.
There are better ways to do that. They might involve a look up tables or magic constants (search for DeBruijn).
The approach I took finally was relying on a processor instruction to do that. That makes the code less portable but it is most likely the fastest way to do that. Free Pascal supports in line assembler and my function looks like this
function getLSB(const Input: Int64): Byte; Assembler;
// Returns the least significant bit of a 64 bits number
// or ERROR if no bit is set
bsf eax, dword ptr Input
bsf eax, dword ptr Input + 04h
add eax, 32
mov eax, ERROR
You must process the input in 2 steps as bsf (bit scan forward) works on 32 bit arguments.
I have similar functions for finding the most significant bit or counting the number of set bits in a BitBoard.