|
From: John R.
|
>>disInstr: unhandled instruction bytes: 0x1E 0x7 0xC3 0x8A 1E push %ds 07 pop %es This copies %ds into %es using only two bytes of code, and without overwriting any other register, and with no net change in visible memory. [x86 has no instruction which moves one segment register to another.] Valgrind(memcheck) should recognize it as an idiom. Such a sequence may be used after x86 "string" opcodes (movs, stos, cmps, scans) to restore the default configuration of segment registers. The x86 string opcodes use %es in a special way, and the real question here is why there was no prior complaint about %es being set up-- to be equal to %gs, for instance. This might be used for some thread manipulation, and if so then any movs/stos/cmps/scans would touch different memory locations: the segment base for %es is added to the offset indicated by the operand addressing in the instruction. Valgrind(memcheck) would have to emulate that segment+offset addition in order to track memory state, and this is expensive in time and complexity. The original poster indicated no such complaint, so my guess is that the "push %ds; pop %es" is in a common tail of "if - else" where one branch _does_ change %es, but the actual execution chose the other path which does not write to %es. Probably the coder could move the "push %es; pop %es" out of the common tail and into the appropriate branch, thus "optimizing" the code. It would be even better to avoid changing %es at all, but the LEA opcode deals only with offset (and does not add the segment base), so this would mean that movs/stos/cmps/scans could not be used on thread-local storage that would otherwise use %gs for addressing. The practical effect is that memset() and memcpy() of thread-local storage must not use stos and movs. -- John Reiser, jreiser@BitWagon.com |