Add support for LEB128 encoded integers (both signed and unsigned). This

is needed for the GAS .uleb128 and .sleb128 directives.

* intnum.c (yasm_intnum_sign): New signedness discovery function.
* intnum.h (yasm_intnum_sign): Prototype.

* intnum.c (yasm_intnum_get_leb128, yasm_intnum_size_leb128): New.
* intnum.h (yasm_intnum_get_leb128, yasm_intnum_size_leb128): Prototype.
* leb128_test.c: New test for intnum-level LEB128 functions.

* bytecode.c (bytecode_leb128): New bytecode and supporting functions.
(yasm_bc_create_leb128): New creation function.
* bytecode.h (yasm_bc_create_leb128): Prototype.

* gas-token.re: Recognize .uleb128 and .sleb128.
* gas-bison.y: Ditto.
(gas_define_leb128): New.
* leb128.asm: New test for GAS .uleb128 and .sleb128 directives.

svn path=/trunk/yasm/; revision=1287
0.5.0rc2
Peter Johnson 20 years ago
parent 8ab7670690
commit 1ddc1272d2
  1. 134
      libyasm/bytecode.c
  2. 9
      libyasm/bytecode.h
  3. 92
      libyasm/intnum.c
  4. 22
      libyasm/intnum.h
  5. 5
      libyasm/tests/Makefile.inc
  6. 159
      libyasm/tests/leb128_test.c
  7. 37
      modules/parsers/gas/gas-bison.y
  8. 2
      modules/parsers/gas/gas-token.re
  9. 3
      modules/parsers/gas/tests/Makefile.inc
  10. 18
      modules/parsers/gas/tests/leb128.asm
  11. 0
      modules/parsers/gas/tests/leb128.errwarn
  12. 448
      modules/parsers/gas/tests/leb128.hex

@ -65,6 +65,17 @@ typedef struct bytecode_data {
unsigned char size;
} bytecode_data;
typedef struct bytecode_leb128 {
/* source data (linked list) */
yasm_datavalhead datahead;
/* signedness (0=unsigned, 1=signed) */
int sign;
/* total length (calculated at finalize time) */
unsigned long len;
} bytecode_leb128;
typedef struct bytecode_reserve {
/*@only@*/ yasm_expr *numitems; /* number of items to reserve */
unsigned char itemsize; /* size of each item (in bytes) */
@ -123,6 +134,15 @@ static int bc_data_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
yasm_output_expr_func output_expr,
/*@null@*/ yasm_output_reloc_func output_reloc);
static void bc_leb128_destroy(void *contents);
static void bc_leb128_print(const void *contents, FILE *f, int indent_level);
static void bc_leb128_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc);
static yasm_bc_resolve_flags bc_leb128_resolve
(yasm_bytecode *bc, int save, yasm_calc_bc_dist_func calc_bc_dist);
static int bc_leb128_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
yasm_output_expr_func output_expr,
/*@null@*/ yasm_output_reloc_func output_reloc);
static void bc_reserve_destroy(void *contents);
static void bc_reserve_print(const void *contents, FILE *f, int indent_level);
static yasm_bc_resolve_flags bc_reserve_resolve
@ -175,6 +195,14 @@ static const yasm_bytecode_callback bc_data_callback = {
bc_data_tobytes
};
static const yasm_bytecode_callback bc_leb128_callback = {
bc_leb128_destroy,
bc_leb128_print,
bc_leb128_finalize,
bc_leb128_resolve,
bc_leb128_tobytes
};
static const yasm_bytecode_callback bc_reserve_callback = {
bc_reserve_destroy,
bc_reserve_print,
@ -462,6 +490,112 @@ yasm_bc_create_data(yasm_datavalhead *datahead, unsigned int size,
return yasm_bc_create_common(&bc_data_callback, data, line);
}
static void
bc_leb128_destroy(void *contents)
{
bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)contents;
yasm_dvs_destroy(&bc_leb128->datahead);
yasm_xfree(contents);
}
static void
bc_leb128_print(const void *contents, FILE *f, int indent_level)
{
const bytecode_leb128 *bc_leb128 = (const bytecode_leb128 *)contents;
fprintf(f, "%*s_Data_\n", indent_level, "");
fprintf(f, "%*sSign=%u\n", indent_level+1, "",
(unsigned int)bc_leb128->sign);
fprintf(f, "%*sElements:\n", indent_level+1, "");
yasm_dvs_print(&bc_leb128->datahead, f, indent_level+2);
}
static void
bc_leb128_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
{
bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)bc->contents;
yasm_dataval *dv;
/*@dependent@*/ /*@null@*/ yasm_intnum *intn;
/* Only constant expressions are allowed.
* Because of this, go ahead and calculate length.
*/
bc_leb128->len = 0;
STAILQ_FOREACH(dv, &bc_leb128->datahead, link) {
switch (dv->type) {
case DV_EMPTY:
break;
case DV_EXPR:
intn = yasm_expr_get_intnum(&dv->data.expn, NULL);
if (!intn) {
yasm__error(bc->line,
N_("LEB128 requires constant values"));
return;
}
/* Warn for negative values in unsigned environment.
* This could be an error instead: the likelihood this is
* desired is very low!
*/
if (yasm_intnum_sign(intn) == -1 && !bc_leb128->sign)
yasm__warning(YASM_WARN_GENERAL, bc->line,
N_("negative value in unsigned LEB128"));
bc_leb128->len +=
yasm_intnum_size_leb128(intn, bc_leb128->sign);
break;
case DV_STRING:
yasm__error(bc->line,
N_("LEB128 does not allow string constants"));
return;
}
}
}
static yasm_bc_resolve_flags
bc_leb128_resolve(yasm_bytecode *bc, int save,
yasm_calc_bc_dist_func calc_bc_dist)
{
bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)bc->contents;
bc->len += bc_leb128->len;
return YASM_BC_RESOLVE_MIN_LEN;
}
static int
bc_leb128_tobytes(yasm_bytecode *bc, unsigned char **bufp, void *d,
yasm_output_expr_func output_expr,
/*@unused@*/ yasm_output_reloc_func output_reloc)
{
bytecode_leb128 *bc_leb128 = (bytecode_leb128 *)bc->contents;
yasm_dataval *dv;
/*@dependent@*/ /*@null@*/ yasm_intnum *intn;
STAILQ_FOREACH(dv, &bc_leb128->datahead, link) {
switch (dv->type) {
case DV_EMPTY:
break;
case DV_EXPR:
intn = yasm_expr_get_intnum(&dv->data.expn, NULL);
if (!intn)
yasm_internal_error(N_("non-constant in leb128_tobytes"));
*bufp += yasm_intnum_get_leb128(intn, *bufp, bc_leb128->sign);
break;
case DV_STRING:
yasm_internal_error(N_("string in leb128_tobytes"));
}
}
return 0;
}
yasm_bytecode *
yasm_bc_create_leb128(yasm_datavalhead *datahead, int sign, unsigned long line)
{
bytecode_leb128 *leb128 = yasm_xmalloc(sizeof(bytecode_leb128));
leb128->datahead = *datahead;
leb128->sign = sign;
return yasm_bc_create_common(&bc_leb128_callback, leb128, line);
}
static void
bc_reserve_destroy(void *contents)
{

@ -141,6 +141,15 @@ void yasm_bc_set_multiple(yasm_bytecode *bc, /*@keep@*/ yasm_expr *e);
/*@only@*/ yasm_bytecode *yasm_bc_create_data
(yasm_datavalhead *datahead, unsigned int size, unsigned long line);
/** Create a bytecode containing LEB128-encoded data value(s).
* \param datahead list of data values (kept, do not free)
* \param sign signedness (1=signed, 0=unsigned) of each data value
* \param line virtual line (from yasm_linemap)
* \return Newly allocated bytecode.
*/
/*@only@*/ yasm_bytecode *yasm_bc_create_leb128
(yasm_datavalhead *datahead, int sign, unsigned long line);
/** Create a bytecode reserving space.
* \param numitems number of reserve "items" (kept, do not free)
* \param itemsize reserved size (in bytes) for each item

@ -477,6 +477,18 @@ yasm_intnum_is_neg1(yasm_intnum *intn)
return (intn->type == INTNUM_BV && BitVector_is_full(intn->val.bv));
}
int
yasm_intnum_sign(yasm_intnum *intn)
{
if (intn->type == INTNUM_UL) {
if (intn->val.ul == 0)
return 0;
else
return 1;
} else
return BitVector_Sign(intn->val.bv);
}
unsigned long
yasm_intnum_get_uint(const yasm_intnum *intn)
{
@ -638,6 +650,86 @@ yasm_intnum_check_size(const yasm_intnum *intn, size_t size, size_t rshift,
return (Set_Max(val) < (long)size);
}
unsigned long
yasm_intnum_get_leb128(const yasm_intnum *intn, unsigned char *ptr, int sign)
{
wordptr val = op1static;
unsigned long i, size;
unsigned char *ptr_orig = ptr;
/* Shortcut 0 */
if (intn->type == INTNUM_UL && intn->val.ul == 0) {
*ptr = 0;
return 1;
}
/* If not already a bitvect, convert value to be written to a bitvect */
if (intn->type == INTNUM_BV)
val = intn->val.bv;
else {
BitVector_Empty(val);
BitVector_Chunk_Store(val, 32, 0, intn->val.ul);
}
if (sign) {
/* Signed mode */
if (BitVector_msb_(val)) {
/* Negative */
BitVector_Negate(conv_bv, val);
size = Set_Max(conv_bv)+2;
} else {
/* Positive */
size = Set_Max(val)+2;
}
} else {
/* Unsigned mode */
size = Set_Max(val)+1;
}
/* Positive/Unsigned write */
for (i=0; i<size; i += 7) {
*ptr = (unsigned char)BitVector_Chunk_Read(val, 7, i);
*ptr |= 0x80;
ptr++;
}
*(ptr-1) &= 0x7F; /* Clear MSB of last byte */
return (unsigned long)(ptr-ptr_orig);
}
unsigned long
yasm_intnum_size_leb128(const yasm_intnum *intn, int sign)
{
wordptr val = op1static;
/* Shortcut 0 */
if (intn->type == INTNUM_UL && intn->val.ul == 0) {
return 1;
}
/* If not already a bitvect, convert value to a bitvect */
if (intn->type == INTNUM_BV)
val = intn->val.bv;
else {
BitVector_Empty(val);
BitVector_Chunk_Store(val, 32, 0, intn->val.ul);
}
if (sign) {
/* Signed mode */
if (BitVector_msb_(val)) {
/* Negative */
BitVector_Negate(conv_bv, val);
return (Set_Max(conv_bv)+8)/7;
} else {
/* Positive */
return (Set_Max(val)+8)/7;
}
} else {
/* Unsigned mode */
return (Set_Max(val)+7)/7;
}
}
void
yasm_intnum_print(const yasm_intnum *intn, FILE *f)
{

@ -135,6 +135,12 @@ int yasm_intnum_is_pos1(yasm_intnum *acc);
*/
int yasm_intnum_is_neg1(yasm_intnum *acc);
/** Simple sign check.
* \param acc intnum
* \return -1 if negative, 0 if zero, +1 if positive
*/
int yasm_intnum_sign(yasm_intnum *acc);
/** Convert an intnum to an unsigned 32-bit value. The value is in "standard"
* C format (eg, of unknown endian).
* \note Parameter intnum is truncated to fit into 32 bits. Use
@ -186,6 +192,22 @@ void yasm_intnum_get_sized(const yasm_intnum *intn, unsigned char *ptr,
int yasm_intnum_check_size(const yasm_intnum *intn, size_t size,
size_t rshift, int rangetype);
/** Output #yasm_intnum to buffer in LEB128-encoded form.
* \param intn intnum
* \param ptr pointer to storage for output bytes
* \param sign signedness of LEB128 encoding (0=unsigned, 1=signed)
* \return Number of bytes generated.
*/
unsigned long yasm_intnum_get_leb128(const yasm_intnum *intn,
unsigned char *ptr, int sign);
/** Calculate number of bytes LEB128-encoded form of #yasm_intnum will take.
* \param intn intnum
* \param sign signedness of LEB128 encoding (0=unsigned, 1=signed)
* \return Number of bytes.
*/
unsigned long yasm_intnum_size_leb128(const yasm_intnum *intn, int sign);
/** Print an intnum. For debugging purposes.
* \param f file
* \param intn intnum

@ -2,6 +2,7 @@
TESTS += bitvect_test
TESTS += floatnum_test
TESTS += leb128_test
TESTS += libyasm/tests/libyasm_test.sh
EXTRA_DIST += libyasm/tests/libyasm_test.sh
@ -19,6 +20,7 @@ EXTRA_DIST += libyasm/tests/unary.hex
check_PROGRAMS += bitvect_test
check_PROGRAMS += floatnum_test
check_PROGRAMS += leb128_test
bitvect_test_SOURCES = libyasm/tests/bitvect_test.c
bitvect_test_LDADD = libyasm.a $(INTLLIBS)
@ -26,3 +28,6 @@ bitvect_test_LDADD = libyasm.a $(INTLLIBS)
floatnum_test_SOURCES = libyasm/tests/floatnum_test.c
floatnum_test_LDADD = libyasm.a $(INTLLIBS)
leb128_test_SOURCES = libyasm/tests/leb128_test.c
leb128_test_LDADD = libyasm.a $(INTLLIBS)

@ -0,0 +1,159 @@
/* $Id$
*
* Copyright (C) 2005 Peter Johnson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#endif
#include <stdio.h>
#include "libyasm/intnum.c"
typedef struct Test_Entry {
/* signedness (0=unsigned, 1=signed) */
int sign;
/* whether input value should be negated */
int negate;
/* input value (as hex string) */
const char *input;
/* correct size returned from both size_leb128 and get_leb128 */
unsigned long outsize;
/* correct return data from get_leb128 */
const unsigned char *result;
} Test_Entry;
static Test_Entry tests[] = {
/* Unsigned values */
{0, 0, "0", 1, (const unsigned char *)"\x00"},
{0, 0, "2", 1, (const unsigned char *)"\x02"},
{0, 0, "7F", 1, (const unsigned char *)"\x7F"},
{0, 0, "80", 2, (const unsigned char *)"\x80\x01"},
{0, 0, "81", 2, (const unsigned char *)"\x81\x01"},
{0, 0, "82", 2, (const unsigned char *)"\x82\x01"},
{0, 0, "3239", 2, (const unsigned char *)"\xB9\x64"},
/* Signed zero value */
{1, 0, "0", 1, (const unsigned char *)"\x00"},
/* Signed positive values */
{1, 0, "2", 1, (const unsigned char *)"\x02"},
{1, 0, "7F", 2, (const unsigned char *)"\xFF\x00"},
{1, 0, "80", 2, (const unsigned char *)"\x80\x01"},
{1, 0, "81", 2, (const unsigned char *)"\x81\x01"},
/* Signed negative values */
{1, 1, "2", 1, (const unsigned char *)"\x7E"},
{1, 1, "7F", 2, (const unsigned char *)"\x81\x7F"},
{1, 1, "80", 2, (const unsigned char *)"\x80\x7F"},
{1, 1, "81", 2, (const unsigned char *)"\xFF\x7E"},
};
static char failed[1000];
static char failmsg[100];
static int
run_test(Test_Entry *test)
{
char *valstr = yasm__xstrdup(test->input);
yasm_intnum *intn = yasm_intnum_create_hex(valstr, 0);
unsigned long size, i;
unsigned char out[100];
int bad;
yasm_xfree(valstr);
if (test->negate)
yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL, 0);
size = yasm_intnum_size_leb128(intn, test->sign);
if (size != test->outsize) {
yasm_intnum_destroy(intn);
sprintf(failmsg, "%ssigned %s%s size() bad size: expected %lu, got %lu!",
test->sign?"":"un", test->negate?"-":"", test->input,
test->outsize, size);
return 1;
}
for (i=0; i<sizeof(out); i++)
out[i] = 0xFF;
size = yasm_intnum_get_leb128(intn, out, test->sign);
if (size != test->outsize) {
yasm_intnum_destroy(intn);
sprintf(failmsg, "%ssigned %s%s get() bad size: expected %lu, got %lu!",
test->sign?"":"un", test->negate?"-":"", test->input,
test->outsize, size);
return 1;
}
bad = 0;
for (i=0; i<test->outsize && !bad; i++) {
if (out[i] != test->result[i])
bad = 1;
}
if (bad) {
yasm_intnum_destroy(intn);
sprintf(failmsg, "%ssigned %s%s get() bad output!",
test->sign?"":"un", test->negate?"-":"", test->input);
return 1;
}
yasm_intnum_destroy(intn);
return 0;
}
int
main(void)
{
int nf = 0;
int numtests = sizeof(tests)/sizeof(Test_Entry);
int i;
if (BitVector_Boot() != ErrCode_Ok)
return EXIT_FAILURE;
yasm_intnum_initialize();
failed[0] = '\0';
printf("Test leb128_test: ");
for (i=0; i<numtests; i++) {
int fail = run_test(&tests[i]);
printf("%c", fail>0 ? 'F':'.');
fflush(stdout);
if (fail)
sprintf(failed, "%s ** F: %s\n", failed, failmsg);
nf += fail;
}
yasm_intnum_cleanup();
printf(" +%d-%d/%d %d%%\n%s",
numtests-nf, nf, numtests, 100*(numtests-nf)/numtests, failed);
return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}

@ -56,6 +56,9 @@ static yasm_bytecode *gas_define_strings(yasm_parser_gas *parser_gas,
static yasm_bytecode *gas_define_data(yasm_parser_gas *parser_gas,
yasm_valparamhead *vps,
unsigned int size);
static yasm_bytecode *gas_define_leb128(yasm_parser_gas *parser_gas,
yasm_valparamhead *vps,
int sign);
static void gas_parser_directive
(yasm_parser_gas *parser_gas, const char *name,
yasm_valparamhead *valparams,
@ -104,8 +107,9 @@ static void gas_parser_directive
%token DIR_BSS DIR_BYTE DIR_COMM DIR_DATA DIR_DOUBLE DIR_ENDR DIR_EXTERN
%token DIR_EQU DIR_FILE DIR_FLOAT DIR_GLOBAL DIR_IDENT DIR_INT DIR_LOC
%token DIR_LCOMM DIR_OCTA DIR_ORG DIR_P2ALIGN DIR_REPT DIR_SECTION
%token DIR_SHORT DIR_SIZE DIR_SKIP DIR_STRING
%token DIR_TEXT DIR_TFLOAT DIR_TYPE DIR_QUAD DIR_WEAK DIR_WORD DIR_ZERO
%token DIR_SHORT DIR_SIZE DIR_SKIP DIR_SLEB128 DIR_STRING
%token DIR_TEXT DIR_TFLOAT DIR_TYPE DIR_QUAD DIR_ULEB128 DIR_WEAK DIR_WORD
%token DIR_ZERO
%type <bc> line lineexp instr
@ -295,6 +299,14 @@ lineexp: instr
yasm_bc_set_multiple($$, $2);
}
| DIR_SLEB128 datavals {
$$ = gas_define_leb128(parser_gas, &$2, 1);
yasm_vps_delete(&$2);
}
| DIR_ULEB128 datavals {
$$ = gas_define_leb128(parser_gas, &$2, 0);
yasm_vps_delete(&$2);
}
/* Floating point data definition directives */
| DIR_FLOAT datavals {
$$ = gas_define_data(parser_gas, &$2, 4);
@ -812,6 +824,27 @@ gas_define_data(yasm_parser_gas *parser_gas, yasm_valparamhead *vps,
return NULL;
}
static yasm_bytecode *
gas_define_leb128(yasm_parser_gas *parser_gas, yasm_valparamhead *vps,
int sign)
{
if (yasm_vps_first(vps)) {
yasm_datavalhead dvs;
yasm_valparam *cur;
yasm_dvs_initialize(&dvs);
yasm_vps_foreach(cur, vps) {
if (!cur->param)
yasm__error(cur_line, N_("missing data value"));
else
yasm_dvs_append(&dvs, yasm_dv_create_expr(cur->param));
cur->param = NULL;
}
return yasm_bc_create_leb128(&dvs, sign, cur_line);
} else
return NULL;
}
static void
gas_parser_directive(yasm_parser_gas *parser_gas, const char *name,
yasm_valparamhead *valparams,

@ -291,12 +291,14 @@ scan:
'.single' { RETURN(DIR_FLOAT); }
'.size' { RETURN(DIR_SIZE); }
'.skip' { RETURN(DIR_SKIP); }
'.sleb128' { RETURN(DIR_SLEB128); }
'.space' { RETURN(DIR_SKIP); }
'.string' { RETURN(DIR_ASCIZ); }
'.text' { RETURN(DIR_TEXT); }
'.tfloat' { RETURN(DIR_TFLOAT); }
'.type' { RETURN(DIR_TYPE); }
'.quad' { RETURN(DIR_QUAD); }
'.uleb128' { RETURN(DIR_ULEB128); }
'.weak' { RETURN(DIR_WEAK); }
'.word' { RETURN(DIR_WORD); }
'.zero' { RETURN(DIR_ZERO); }

@ -15,6 +15,9 @@ EXTRA_DIST += modules/parsers/gas/tests/datavis2.hex
EXTRA_DIST += modules/parsers/gas/tests/jmpcall.asm
EXTRA_DIST += modules/parsers/gas/tests/jmpcall.errwarn
EXTRA_DIST += modules/parsers/gas/tests/jmpcall.hex
EXTRA_DIST += modules/parsers/gas/tests/leb128.asm
EXTRA_DIST += modules/parsers/gas/tests/leb128.errwarn
EXTRA_DIST += modules/parsers/gas/tests/leb128.hex
EXTRA_DIST += modules/parsers/gas/tests/reggroup-err.asm
EXTRA_DIST += modules/parsers/gas/tests/reggroup-err.errwarn
EXTRA_DIST += modules/parsers/gas/tests/reggroup.asm

@ -0,0 +1,18 @@
.data
.uleb128 0
.uleb128 2
.uleb128 127
.uleb128 128
.uleb128 129
.uleb128 130
.uleb128 12857
.sleb128 0
.sleb128 2
.sleb128 -2
.sleb128 127
.sleb128 -127
.sleb128 128
.sleb128 -128
.sleb128 129
.sleb128 -129

@ -0,0 +1,448 @@
7f
45
4c
46
01
01
01
00
00
00
00
00
00
00
00
00
01
00
03
00
01
00
00
00
00
00
00
00
00
00
00
00
d0
00
00
00
00
00
00
00
34
00
00
00
00
00
28
00
06
00
01
00
00
00
00
00
00
00
00
00
00
00
00
00
00
02
7f
80
01
81
01
82
01
b9
64
00
02
7e
ff
00
81
7f
80
01
80
7f
81
01
ff
7e
00
00
00
2e
74
65
78
74
00
2e
64
61
74
61
00
2e
73
74
72
74
61
62
00
2e
73
79
6d
74
61
62
00
2e
73
68
73
74
72
74
61
62
00
00
00
2d
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
01
00
00
00
00
00
00
00
00
00
00
00
04
00
f1
ff
00
00
00
00
00
00
00
00
00
00
00
00
03
00
05
00
00
00
00
00
00
00
00
00
00
00
00
00
03
00
04
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
1d
00
00
00
03
00
00
00
00
00
00
00
00
00
00
00
5c
00
00
00
27
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
0d
00
00
00
03
00
00
00
00
00
00
00
00
00
00
00
84
00
00
00
03
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
15
00
00
00
02
00
00
00
00
00
00
00
00
00
00
00
88
00
00
00
40
00
00
00
02
00
00
00
04
00
00
00
04
00
00
00
10
00
00
00
01
00
00
00
01
00
00
00
06
00
00
00
00
00
00
00
40
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
10
00
00
00
00
00
00
00
07
00
00
00
01
00
00
00
00
00
00
00
00
00
00
00
40
00
00
00
1a
00
00
00
00
00
00
00
00
00
00
00
04
00
00
00
00
00
00
00
Loading…
Cancel
Save