From reading these and other posts from PA3040 I think I can see where the confusion is coming from:
It's all to do with the number radix we normally use. In normal life we use decimal (base 10), but in programming this is not efficient because the underlying numbers are binary and to keep referring to long strings of 1 and 0 would be confusing and take a lot of typing. We could use the binary numbers for zero to 9 like this:
0 = 0000
1 = 0001
2 = 0010
3 = 0011
4 = 0100
5 = 0101
6 = 0110
7 = 0111
8 = 1000
9 = 1001
It is sometimes used like that and we call it BCD (Binary Coded Decimal). For example 123 in decimal would be 0001 0010 0011 in BCD. Note how many bits are needed though.
In programming that is not efficient and you will see the reason is that some of the possible binary combinations are not utilized. To make best use of binary, instead of decimal we use hexadecimal (base 16) which adds these extra 'numbers':
A = 1010
B = 1011
C = 1100
D = 1101
E = 1110
F = 1111
For example 3AF in hexadecimal would be 0011 1010 1111 in binary. As there could be confusion over the radix, we usually indicate hexadecimal by adding 'H' or '0x' in front of the number. Also to make it easier to read, we group the binary bits into groups of four, starting from the right (least significant bit) and working to the right.
Now going back to your original question
The opcode you saw for "movlw 0xff" (note the 0x) was converted by the assembler to 30FF.
Split the 30FF into individual characters 3 0 F F and convert each into binary, you get: 0011 0000 1111 1111 which is the bit pattern of the PIC opcode for that instruction. The first two zeros are not physically present in the PIC because it only has a 14 bit instruction set, thats why the first hex number in any PIC16 instruction is never greater than 3.
Does that explain.
Brian.