2.2.2 E8 Call Translation
E8 call translation is an optional feature that can be used when the data to compress contains x86 instruction sequences. E8 translation operates as a preprocessing stage before compressing each chunk, and the compressed stream header contains a bit that indicates whether the decoder shall reverse the translation as a postprocessing step after decompressing each chunk.
The x86 instruction beginning with a byte value of 0xE8 is followed by a 32-bit, little-endian relative displacement to the call target. When E8 call translation is enabled, the following preprocessing steps are performed on the uncompressed input before compression (assuming little-endian byte ordering):
Let chunk_offset refer to the total number of uncompressed bytes preceding this chunk.
Let E8_file_size refer to the caller-specified value given to the compressor or decoded from the header of the compressed stream during decompression.
The following example shows how E8 translation is performed for each 32-KB chunk of uncompressed data (or less than 32 KB if last chunk to compress).
-
if (( chunk_offset < 0x40000000 ) && ( chunk_size > 10 )) for ( i = 0; i < (chunk_size – 10); i++ ) if ( chunk_byte[ i ] == 0xE8 ) long current_pointer = chunk_offset + i; long displacement = chunk_byte[ i+1 ] | chunk_byte[ i+2 ] << 8 | chunk_byte[ i+3 ] << 16 | chunk_byte[ i+4 ] << 24; long target = current_pointer + displacement; if (( target >= 0 ) && ( target < E8_file_size+current_pointer)) if ( target >= E8_file_size ) target = displacement – E8_file_size; endif chunk_byte[ i+1 ] = (byte)( target ); chunk_byte[ i+2 ] = (byte)( target >> 8 ); chunk_byte[ i+3 ] = (byte)( target >> 16 ); chunk_byte[ i+4 ] = (byte)( target >> 24 ); endif i += 4; endif endfor endif
After decompression, the E8 scanning algorithm is the same. The following example shows how E8 translation reversal is performed.
-
long value = chunk_byte[ i+1 ] | chunk_byte[ i+2 ] << 8 | chunk_byte[ i+3 ] << 16 | chunk_byte[ i+4 ] << 24; if (( value >= -current_pointer ) && ( value < E8_file_size )) if ( value >= 0 ) displacement = value – current_pointer; else displacement = value + E8_file_size; endif chunk_byte[ i+1 ] = (byte)( displacement ); chunk_byte[ i+2 ] = (byte)( displacement >> 8 ); chunk_byte[ i+3 ] = (byte)( displacement >> 16 ); chunk_byte[ i+4 ] = (byte)( displacement >> 24 ); endif
The first bit in the first chunk in the LZXD bitstream (following the 2-byte, chunk-size prefix described in section 2.2.1) indicates the presence or absence of two 16-bit fields immediately following the single bit. If the bit is set, E8 translation is enabled for all the following chunks in the stream using the 32-bit value derived from the two 16-bit fields as the E8_file_size provided to the compressor when E8 translation was enabled. Note that E8_file_size is completely independent of the length of the uncompressed data. E8 call translation is disabled after the 32,768th chunk (after 1 gigabyte (GB) of uncompressed data).
Field |
Comments |
Size |
---|---|---|
E8 translation |
0-disabled, 1-enabled |
1 bit |
Translation size high word |
Only present if enabled |
0 or 16 bits |
Translation size low word |
Only present if enabled |
0 or 16 bits |