§ XCHG rm, r

Эта инструкция обменивает операнды местами. Операнд может находится в памяти или в регистре.
1// XCHG rm, r
2case 0x86:
3case 0x87:
4
5    i_size = opcode_id & 1;
6    i_op1  = get_rm(i_size);
7    i_op2 = get_reg(i_size);
8    put_rm(i_size, i_op2);
9    put_reg(i_size, i_op1);
10    break;
Как видно из кода, берется из опкода размер byte|word, прочитываются операнды и записываются обратно в ином порядке.

§ LES, LDS r, rm

Эта инструкция читает 4 байта из эффективного адреса и записываются младшие 2 байта в указанный регистр r (16 бит), а старшие 2 байта либо в регистр ES, либо в DS.
1case 0xC4:
2case 0xC5:
3
4    i_tmp = SEGREG(segment_id, i_ea);
5    i_op1 = rd(i_tmp, 2);
6    i_op2 = rd(i_tmp+2, 2);
7
8    regs16[i_reg] = i_op1;
9    regs16[opcode_id == 0xC4 ? REG_ES : REG_DS] = i_op2;
10    break;
Указать в качестве второго операнда регистр нельзя, будет неопределенный ответ, это считается ошибкой. На самом деле указать можно, но процессор себя поведет неадекватно в этом случае, а точнее, он сгенерирует ошибку #UD, undefined instruction.
Коды выкладывать сегодня не буду, потому что тут совсем небольшие доработки.
Следующий материал