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