On 6 May 2017 08:09 -0700, from corey(a)lod.com (Corey Lindsly):
Anyway, I reached one point in the assembly code that
I simply could not
understand. It seemed like a mistake, and I went through it again and
again until I finally realized what it was doing. There was a branch/loop
that jumped to the middle of a multi-byte machine instruction, so that
branch had to be disassembled and stepped separately until it "synced" up
with the other branch again. Maybe this is standard practice in
programming (I don't know) but at the time I thought, what kind of evil
genius devised this to save a few bytes of memory?
IIRC, that _was_ a common trick at least on machines of that class. It
did have the potential to save a few bytes, yes (more if the
instructions were such that you'd get some _other, desired_, behavior
by jumping into the middle of one with some specific state), but it
also foiled lots of disassemblers: Simply disassembling a binary from
start to finish would yield nonsense in those locations, as you
experienced. It thus basically forced you to single-step those
instructions to figure out what was going on from the binary.
I'm pretty sure it works on every architecture with variable-length
instructions and arbitrary jump capability, as long as you have
control over the specific machine instructions generated (such as if
you are programming in assembler). Of course, it _is_ also a total
nightmare to maintain such code.
I would absolutely not say that doing something like that is standard
practice in modern programming. Even in microcontrollers, where
program and data memory can be scarce even today, I would argue that
the costs would not outweigh the benefits by a long shot.
--
Michael Kjörling •
https://michael.kjorling.se • michael(a)kjorling.se
“People who think they know everything really annoy
those of us who know we don’t.” (Bjarne Stroustrup)