I'm trying to load varios bytes from a struct in assembly. I found a good explanation here for uint. While this is working for uint and the whole memory slot i cant figure out how to get a bytes1 or bytes12 variable from the struct.

``````contract Storage {

mapping(uint256 => turmite) public turmites;

struct turmite {
bytes1 state;
bytes12 baserule;
}

bytes1 state = hex"02";
constructor(){
turmites[1] = turmite(
state,
0xff0801ff0201ff0000000001
);
}

function retrieve(uint id) public{
turmite storage data = turmites[id];
bytes12 b;
bytes1 a;
bytes32 completeslot;
assembly {
completeslot := w
a := and(w, 0xff)
}
}
}
``````

Bytes & Strings are left aligned, while numbers (i.e., uintX) are right aligned.

• bytes32(bytes1(0xFF)) -> 0xFF0...00
• uint256(uint8(0xFF)) -> 0x00...0FF

``````function test() public view returns (bytes1) {
uint256 value = 0xFF00000000000000000000000000000000000000000000000000000000000000;
bytes1 rvalue;

assembly {
rvalue := value
}

return rvalue; // 0xFF
}
``````

SLOAD returns a uint256, when trying to put this value in a bytes1 you are actually getting the 32th byte of the uint (Throughout this answer, byte 32 is far left, byte 0 is far right), not the 1st. With bytes12, you get the range 32 to 20 instead of 12 to 0.

This is exactly what happens with :

``````// clears bytes 32 to 1 and puts byte 32 into a
// because a is byte1 : left aligned
a := and(w, 0xff)
``````

You could work directly on ints and only convert before returning outside the assembly block like so :

``````function retrieve(uint id) public view returns (bytes1, bytes12) {
turmite storage data = turmites[id];
uint96 b;
uint8 a;

assembly {
a := w
b := shr(8, w)
}

return (bytes1(a), bytes12(b));
}
``````

Or stick with bytesX and shift your values left as this is where they will be picked up :

``````  function retrieve(uint id) public view returns (bytes1, bytes12) {
turmite storage data = turmites[id];
bytes12 b;
bytes1 a;

assembly {