Extracting bitfields


Here’s a useful routine bits I wrote for the uLisp RISC-V assembler, but it has applications in programming for microcontroller boards such as the Arduino. It extracts a single bit, or a bit field of several bits, from the number provided as its first parameter:

(defun bits (x a &optional b)
  (if b (logand (ash x (- b)) (1- (ash 1 (- a b -1))))
    (logand (ash x (- a)) 1)))

To extract a single bit provide the bit position of the bit as the second argument; for example:

> (bits #b1001011001010011 4)

To extract a bitfield, specify the starting and ending bit positions, inclusive; for example:

> (format t "~b" (bits #b1001011001010011 6 2))

Note that I’m taking advantage of the ~b format directive added in uLisp 3.5 to show the result in binary.


Looks similar to ldb, although that doesn’t have the reversing ability.

ldb and dpb are CL functions that would definitely be useful in uLisp.


I’ll need to read about ldb and dpb - thanks!

Just realised bits can be written more simply:

(defun bits (x a &optional (b a))
  (logand (ash x (- b)) (1- (ash 1 (- a b -1)))))


ldb and dpb, for reference.

They sorta-depend on the additional function byte, because they take an implementation-defined representation of what a byte is. (CL had a lot of legacy stuff to contend with.) SBCL uses a simple cons cell, though, which I imagine is inherited from CMUCL.


It looks like:

(ldb (byte length position) arg)

is equivalent to my:

(bits arg (+ position length -1) position)