Hacker News new | ask | show | jobs
by rep_lodsb 884 days ago
Rather than "jumping into the middle of an instruction" (which to me implies some crazy trickery where both the original instruction and the middle of it do something useful, like the sibling comment about biology), a more straightforward way of looking at it is that the "jumped-into" instruction is actually a single-byte jump which skips over the one or two following bytes - and those shouldn't be considered to be part of the instruction at all.

The opcode will of course perform whatever function it was normally intended for, but it will have been chosen by the programmer to be something that doesn't affect the state of the program in a meaningful way. So it really is just a shorter form of jump, not something beyond the understanding of mere humans - you could always replace it with a regular jump and get the same semantics.

CPUs at the time didn't have branch prediction. The 8086 did prefetch code, but always linearly, and even an unconditional jump would flush that prefetch queue. So having an instruction like "CMP AX,xxxx" (where xxxx=any 16 bit immediate value) would be both shorter and faster than the "proper" jump instruction, while affecting only the flag register.

And on the 8080, there was no short (8 bit relative) jump instruction, so this kind of trick even saved two bytes instead of just one.

1 comments

> Rather than "jumping into the middle of an instruction" (which to me implies some crazy trickery where both the original instruction and the middle of it do something useful, like the sibling comment about biology)

Doesn't "jumping into the middle of the instruction" just mean that decoding from the middle is another instruction, then when decoding from the start of it?

E.g.:

    IMUL -> 0x0FAF 
    SCASW -> 0xAF
Almost any random bytes can be decoded as some instruction - most of them are not useful. The essence of this jump-forward-by-one-or-two-bytes trick is that it performs an operation which doesn't have an effect on the program, so it can be considered to be a single-byte jump opcode, and its "immediate operand" as a separate instruction which is simply skipped over.

You could define assembler macros named something like "SKIP1" and "SKIP2" that emit these opcode bytes (3Ch / 3Dh), and use them just like a jump, provided that you don't care about the flags.

My point was that this is easier to reason about than the more general case where (working) code jumps into the middle of an instruction that already does something else - that either takes extreme cleverness, or evolution over millions of years.