There are many different types of mov. Opcode bytes that can mean mov (not all of them always mean mov) are 88 through 8C, 8E, A0 through A3, B0 through BF, C6 and C7 (the last two only mean mov if the r/m field in their ModRM byte is 0).
There is also (depending on what you want to group with movs) movs to/from control and debug registers (0F 20 through 0F 23).
B81B1A is in a group of instructions that spans B8 through BF, based on the destination register (which is encoded in the opcode). That you saw an 8 was because the destination is ax, it has nothing to do with the 8 in 8B (where both the 8 and the B are truly part of the opcode and not some sneaky operand).
mov is complicated. You'll find much more consistency with for example the simple ALU instructions (add, or, adc, sbb, and, sub, xor, cmp are 0 through 7 respectively), that you can all encode with the same function that takes their index as parameter but further doesn't care which one it is (there are still several cases within that function of course). Other potentially useful groups are the "instructions without operands", "instructions with 1 operand and a fixed r field" and "instructions that only have an r, r/m-form"