我正在尝试使用tcl将32位十六进制地址拆分为多个字段,然后显示每个字段,然后将少数字段分配给另一个变量。我在下面尝试但是我没有成功。在这方面你能帮我吗?
//pseudo code that I want to achieve
field1 = addr_in[31:30]
field2 = addr_in[29:14]
field3 = addr_in[13:11] ##field 3 value
field4 = addr_in[10:1]
field5 = addr_in[0]
addr_out = {field3, field2, field4}
print field1,field2,...field5 and addr_out
...
我尝试过list lassign,但后来意识到字符串范围是最好用的。
## actual code below
#! /usr/bin/tclsh
set addr "abcd1234" ## assigning a value to addr
puts $addr
set field1 [string range $addr 0 1] ## this sets field1 as ab.
set field2 [string range $addr 18 20] ## doesn't print anything
puts $field2
set field3 [string range $addr 2 17]
puts $field3
set field4 [string range $addr 21 end-1]
puts $field4
set field5 [string index $addr end]
puts $field5
set addr_out [concat $field3 $field2 $field4]
puts $addr_out
exit 0
### end of the code
但是意识到field1变量只会打印" ab"代替 addr_in [31:30]位以及field2,field3无法显示,因为它们的范围超出范围,所以我尝试使用二进制格式H * $ field1将$ addr转换为二进制,然后将其从高位变为低位然后得到每个字段值,但无法得到它。
也在下面尝试过:
set field1 [string range $addr 0 1]
puts $field1 [binary format H* $addr field1]
感谢您的帮助。
答案 0 :(得分:0)
要提取位,我们首先要将十六进制数转换为位串;我们可以使用scan
和format
执行此操作。 (助记符:%x
用于处理 x 值,%b
用于处理 b inary值。)
set bits [format "%032b" [scan $addr "%x"]]
然后我们可以使用string range
(请记住,此时你已经有效地获得了一个大端值):
set field1 [string range $bits 30 31]
如果您想将其转换为小数,再次scan
:
set field1value [scan $field1 "%b"]
我们也可以一次提取多个字段,然后转换为十进制:
scan $bits "%1b%10b%3b%16b%2b" field5 field4 field3 field2 field1
(使用s
代替b
自行获取位字符串。)
如果您使用的是旧版Tcl,则可能需要使用binary format
和binary scan
。我发现它们比普通format
和scan
更难使用,但您可能不同意。例如,要将地址转换为位串...
binary scan [binary format "H*" $addr] "Bu*" bits