查找字节内存位置中的位地址
Finding the address of bits in a byte memory location
我在 0x31011 处有一个存储位置,用于存储 16 个 1 位符号的数据。这些符号中的每一个都有不同的起始位位置来存储它们的信息:
第一个符号:0x31011 --> 起始位在位 0
第二个符号:0x31011 --> 起始位在位 1
第三个符号:0x31011 --> 第 2 位开始位
...
第 14 个符号:0x31011 --> 第 13 位开始位
第 15 个符号:0x31011 --> 第 14 位开始位
第 16 个符号:0x31011 --> 第 15 位开始位
0x31011的十六进制转二进制为:110001000000010001
如果可能的话,我希望对如何检索每个符号的地址的理解有所启发。我的理解是,我必须为这些符号中的每一个使用 0x31011 处的基地址,然后从该位置提取值,然后使用 AND 运算符进行位掩码,然后右移。所以我最初的想法是不能调用基地址的子地址。
例如,如果我想在第 0 位找到第一个符号的值,假设 0x31011 处的值是 0000001100110001:
1:取0x31011处的值--> 0000001100110001
2:应用掩码:C7 --------------> 0000000011000111
---------------------------------------------- ------------------------------ &
3:查找第一个符号的值 0000000000000001
如果我想在第 1 位找到第二个符号的值,假设 0x31011 处的值为 00000001100110001:
1:取0x31011处的值--> 0000001100110001
2:应用掩码:C6 --------------> 0000000011000110
---------------------------------------------- ------------------------------ &
3: 查找第二个符号的值 ------> 0000000000000000
4:右移结果>> 1 ----------> 0000000000000000
如果我想在第 2 位找到第 3 个符号的值,假设 0x31011 处的值为 00000001100110001:
1:取0x31011处的值--> 0000001100110001
2:应用掩码:C6 --------------> 0000000011000110
---------------------------------------------- ------------------------------ &
3:查找第 3 个符号的值 ------> 0000000000000000
4:右移结果>> 2 ----------> 0000000000000000
.....
如果我想在第 15 位找到第 16 个符号的值,假设 0x31011 处的值为 00000001100110001:
1:取0x31011处的值--> 0000001100110001
2:应用掩码:80C6 ----------> 1000000011000110
---------------------------------------------- ------------------------------ &
3: 查找第 16 个符号的值 ------> 0000000000000000
4:右移结果>> 15 ------> 0000000000000000
内存通常只能按字节寻址,不能按位寻址。要表示单个位的地址,您需要一个常规地址和一个位偏移量。
但是,某些 ISA 确实具有一定的位寻址内存容量。 The 8051 microcontroller's bit-addressable memory 是一个著名的例子。但是位 set/clear/complement 和位上分支指令仅适用于 "direct" 寻址模式,因此您不能传递位的地址,除非您使用自修改代码。地址 00-7F 与字节 load/store 指令一起使用时是完整字节,但与位指令一起使用时是前 16 个字节的位。
除了特殊的 ISA 功能(例如可以使用位寻址的指令)之外,您遇到了软件问题。单个位不能直接寻址。
您只能将其作为包含它的字节或字的一部分来读取。
不过,您当然可以将其位置表示为普通字节地址 + 位偏移量。例如,像这样的 C 函数很容易在任何具有指针寄存器和右移的普通 ISA 上实现:
bool get_bit(const char *location, int bit_offset) {
unsigned char tmp = *location;
return (tmp >> bit_offset) & 1;
}
例如在 x86-64 上:
movzx eax, byte [rdi] ; load the byte
bt eax, esi ; CF = bit at position ESI
setc al ; set AL = CF
ret
在真实地址不需要像寄存器一样多的位的机器上,您可以将位地址编码为单个整数值,并在低 3 位中进行位偏移。 (或者对于具有更大字节的机器来说更多位)。然后要使用它,您需要右移以获得实际的机器地址,并屏蔽以提取位偏移以用作右移计数。
我在 0x31011 处有一个存储位置,用于存储 16 个 1 位符号的数据。这些符号中的每一个都有不同的起始位位置来存储它们的信息:
第一个符号:0x31011 --> 起始位在位 0
第二个符号:0x31011 --> 起始位在位 1
第三个符号:0x31011 --> 第 2 位开始位
...
第 14 个符号:0x31011 --> 第 13 位开始位
第 15 个符号:0x31011 --> 第 14 位开始位
第 16 个符号:0x31011 --> 第 15 位开始位
0x31011的十六进制转二进制为:110001000000010001
如果可能的话,我希望对如何检索每个符号的地址的理解有所启发。我的理解是,我必须为这些符号中的每一个使用 0x31011 处的基地址,然后从该位置提取值,然后使用 AND 运算符进行位掩码,然后右移。所以我最初的想法是不能调用基地址的子地址。
例如,如果我想在第 0 位找到第一个符号的值,假设 0x31011 处的值是 0000001100110001:
1:取0x31011处的值--> 0000001100110001
2:应用掩码:C7 --------------> 0000000011000111
---------------------------------------------- ------------------------------ &
3:查找第一个符号的值 0000000000000001
如果我想在第 1 位找到第二个符号的值,假设 0x31011 处的值为 00000001100110001:
1:取0x31011处的值--> 0000001100110001
2:应用掩码:C6 --------------> 0000000011000110
---------------------------------------------- ------------------------------ &
3: 查找第二个符号的值 ------> 0000000000000000
4:右移结果>> 1 ----------> 0000000000000000
如果我想在第 2 位找到第 3 个符号的值,假设 0x31011 处的值为 00000001100110001:
1:取0x31011处的值--> 0000001100110001
2:应用掩码:C6 --------------> 0000000011000110
---------------------------------------------- ------------------------------ &
3:查找第 3 个符号的值 ------> 0000000000000000
4:右移结果>> 2 ----------> 0000000000000000
.....
如果我想在第 15 位找到第 16 个符号的值,假设 0x31011 处的值为 00000001100110001:
1:取0x31011处的值--> 0000001100110001
2:应用掩码:80C6 ----------> 1000000011000110
---------------------------------------------- ------------------------------ &
3: 查找第 16 个符号的值 ------> 0000000000000000
4:右移结果>> 15 ------> 0000000000000000
内存通常只能按字节寻址,不能按位寻址。要表示单个位的地址,您需要一个常规地址和一个位偏移量。
但是,某些 ISA 确实具有一定的位寻址内存容量。 The 8051 microcontroller's bit-addressable memory 是一个著名的例子。但是位 set/clear/complement 和位上分支指令仅适用于 "direct" 寻址模式,因此您不能传递位的地址,除非您使用自修改代码。地址 00-7F 与字节 load/store 指令一起使用时是完整字节,但与位指令一起使用时是前 16 个字节的位。
除了特殊的 ISA 功能(例如可以使用位寻址的指令)之外,您遇到了软件问题。单个位不能直接寻址。
您只能将其作为包含它的字节或字的一部分来读取。
不过,您当然可以将其位置表示为普通字节地址 + 位偏移量。例如,像这样的 C 函数很容易在任何具有指针寄存器和右移的普通 ISA 上实现:
bool get_bit(const char *location, int bit_offset) {
unsigned char tmp = *location;
return (tmp >> bit_offset) & 1;
}
例如在 x86-64 上:
movzx eax, byte [rdi] ; load the byte
bt eax, esi ; CF = bit at position ESI
setc al ; set AL = CF
ret
在真实地址不需要像寄存器一样多的位的机器上,您可以将位地址编码为单个整数值,并在低 3 位中进行位偏移。 (或者对于具有更大字节的机器来说更多位)。然后要使用它,您需要右移以获得实际的机器地址,并屏蔽以提取位偏移以用作右移计数。