如何将给定八位字节(字节)的最后n位设置为零?

Sim*_*Sim 2 lisp bit-manipulation common-lisp

我得到一个八位字节(字节)和许多相关位,我想保留该给定字节的前n个(相关位)并将剩余的位设置为零.

例如

前4位相关的数字217将转换为208

0                    0
0 1 2 3 4 5 6 7      0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+  ==> +-+-+-+-+-+-+-+
1 1 0 1 1 0 0 1      1 1 0 1 0 0 0 0
Run Code Online (Sandbox Code Playgroud)

前8个(或更多)位相关的数字255根本不会改变

0                    0
0 1 2 3 4 5 6 7      0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+  ==> +-+-+-+-+-+-+-+
1 1 1 1 1 1 1 1      1 1 1 1 1 1 1 1
Run Code Online (Sandbox Code Playgroud)

我写了这个函数来解决问题

(defun list-of-bits (integer)
  (let ((bits '()))
    (dotimes (position (integer-length integer) bits)
      (push (ldb (byte 1 position) integer) bits))))

(defun calculate-octet (byte rel-bits)
  (if (< rel-bits 8)
      (parse-integer 
       (FORMAT nil "~{~a~}"
           (replace (list-of-bits byte)
            '(0 0 0 0 0 0 0 0) 
            :start1 rel-bits
            :end1 8
            :start2 0
            :end2 rel-bits))
       :radix 2)
      byte))
Run Code Online (Sandbox Code Playgroud)

但这个解决方案似乎有两个原因

  1. 它在处理之前将整数拆分为一个列表

  2. 它将列表打印成一个再次解析的字符串

我知道common-lisp提供了直接访问位和字节(ldb,logbitp)的函数,但我无法找到一种方法来将它们用于我的问题.

有没有办法更有效地解决问题(或至少更优雅)?

Rai*_*wig 7

CL-USER 6 > (mask-field (byte 4 4) 217)
208
Run Code Online (Sandbox Code Playgroud)

另请注意,它不会屏蔽原始数字的字段,但会在屏蔽位字段时返回一个新数字.


Lar*_*off 6

已有三个答案,所以我不妨再添两个:

没有人建议DPB.对PDP-10的点头总是很好.

(defun calculate-octet (byte bits)
  (dpb 0 (byte bits bits) byte))
Run Code Online (Sandbox Code Playgroud)

再次与LOGAND.

(defun calculate-octet (byte bits)
  (logand byte (ash -1 (- 8 bits))))
Run Code Online (Sandbox Code Playgroud)