Disassembly of Farbrausch's "fr-016: bytes"
Kragen Javier Sitaker
kragen at canonical.org
Sun Dec 7 19:26:13 EST 2008
Hi, haven't heard from you in a while! How have you been?
On Thu, Nov 27, 2008 at 12:37:36AM +0100, Dave Long wrote:
> I was testing out a rudimentary python 16-bit x86 assembler with the
> code from:
>
> http://canonical.org/~kragen/demo/fr-016.html
>
> and, although my source:
>
> >org 100
> >mov ax,13
> >int 10
> >les bp,[bx]
> >
> >l loop
> >stosb
> >adc ax,di
> >adc ax,1132
> >jmp loop
>
>
> results in a slightly different 15 bytes:
>
> 0000000: b813 00cd 10c4 2faa 11f8 1532 11eb f8 ....../....2...
>
> I still get the same visual output in QEMU.
It *is* animated, I assume?
Note that the 1132 in the original was 1132 decimal; it seems to have
become 3211 hex in your output program.
> I think the 1132 is an immediate, and the FS override is there (a) as
> padding or (b) to potentially confuse disassemblers.
Well, the original instruction is 64 13 06 6c 04. 6c 04 is 0x46C, 1132
decimal. Intel document 253666 p. 3-27 says that the "13" opcode is for
"ADC r16, r/m16" or the 32-bit equivalent; immediate adds use the opcode
bytes 14, 15, 80, 81, or 83. (64 is the FS prefix, says p. 2-2.) So I
don't think it's an immediate; I think it's a memory address.
QEMU seems to agree with me, in that twiddling the memory at address
FS:0x046C via GDB caused a change in behavior --- it wouldn't have if
QEMU interpreted the operand as an immediate.
It's definitely padding/obfuscation though. MS-DOS machines don't have
memory-mapped I/O in any of the plausible places it could be reading
from, so reading the memory is side-effect-free; it could just as easily
have used `adc ax, $increment`, as your version does (using the opcode
byte 15), which would have been three bytes instead of five, and much
less mysterious.
My hypothesis is that ancient MS-DOS versions wouldn't have initialized
FS because they didn't know about it, so it would have remained at
whatever the processor initialized it to at startup, probably 0; FreeDOS
initializing it to the same as the other segment registers is an
incompatibility from the point of view of this program.
> dc -e '16i2o 1132p' yields 1000100110010, so it seems reasonable that
> the second adc helps create a nice LFSR-like term. But I don't
> understand why your attempts at manually removing the FS override
> wouldn't have given the same behavior that I see.
I think it's because of the 13 vs. 15 opcode difference.
Regards,
Kragen
More information about the Kragen-discuss
mailing list