More often than not, you work with unsigned numbers while hand-writing assembly. Of course, this is not always the case, and C's int promotions should be implemented somehow, right?
Let's start by explaining two's complement at the bit level. First of all, the topmost bit, when set, indicates a negative number, and when clear, a non-negative nne. If it's clear, the stuff acts as you would expect. That is, 0 is written 0x00000000, and 2147483647 is written 0x7FFFFFFF. However, for any negative number N, in order to get its absolute value, you have to do ~N-1, with all respective wrap-arounds. This lends into -1 being written 0xFF, and -2147483648 being written 0x80. This has some nice side effects, such that -0 == 0 and addition/subtraction is the same operation for all numbers.
Now, to your code....
XOR EAX,EAX
As a mathematical rule, exclusive-OR'ing something against itself will always yield zero as a result. So, you can think of this like an optimized `MOV EAX, 0'. BTW, you may want to read why XOR is better for this. Then...
MOV AX, BX
MOV is an instruction that literally means "to copy the bits as-is". That is, all cleared bits in the source are respectively cleared in the destination, and all set bits in the source are respectively set in the destination. In this case, AX will now contain an exact copy of BX's contents. In the x86 architecture, EAX, EBX, ECX, and EDX are all divided this way...
________________ ________ ____ ____
| ERX | RX | RH | RL |
|________________|________|____|____|
\_________________________________/
| \________________/
32 bits | \__/
16 bits ||
8 bits
This means that for each register R, ERX represents all of its 32 bits, RX represents its lower 16 bits, RH represents the higher byte of its lower 16 bits, and RL represents the lower byte of its lower 16 bits. Thus, returning to your code, and assuming BX contains 0xFFFF (-1 in two's complement), this is what happens...
______________ __________________________________ __________________________________
| Instruction | EAX | EBX |
|______________|__________________________________|__________________________________|
| XOR EAX, EAX | 00000000000000000000000000000000 | 00000000000000001111111111111111 |
|______________|__________________________________|__________________________________|
| MOV AX, BX | 00000000000000001111111111111111 | 00000000000000001111111111111111 |
|______________|__________________________________|__________________________________|
Then, if we interpret AX as a two's complement number, we get the right answer, that is, -1. However, if we interpret EAX as a two's complement number, we get a wrong answer, 65535. In order to do this correctly, we have to do a sign-extended move. This means that the instruction will take into account the fact that the value is in two's complement form and will thus manipulate it correctly. See, for instance...
_______________ __________________________________ __________________________________
| Instruction | EAX | EBX |
|_______________|__________________________________|__________________________________|
| MOVSX EAX, BX | 11111111111111111111111111111111 | 00000000000000001111111111111111 |
|_______________|__________________________________|__________________________________|
Now, interpreting EAX as a 32-bit two's complement number will yield the right answer, -1. This is (yet) another advantage of two's complement. You can sign-extend by just copying the top-most bit as many times as needed.