diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2020-05-30 21:06:13 +0200 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2020-05-30 21:06:13 +0200 |
commit | 0307ad956911c1fbb526e002e2611f2037d986f2 (patch) | |
tree | f53d5be70f8d0683e6bf8500bfc408d49de82206 | |
parent | de5d9c5d1b735e95a20a8671d38697f1c7e638ea (diff) | |
download | compilertests-0307ad956911c1fbb526e002e2611f2037d986f2.tar.gz compilertests-0307ad956911c1fbb526e002e2611f2037d986f2.tar.bz2 |
asm-i386:
started to support strings in db
fixed embarrassingly wrong parser for hexadecimal numbers
-rw-r--r-- | ecomp-c/asm-i386.c | 90 | ||||
-rw-r--r-- | ecomp-c/tests/asm-i386/mov.asm | 5 |
2 files changed, 88 insertions, 7 deletions
diff --git a/ecomp-c/asm-i386.c b/ecomp-c/asm-i386.c index 2e33189..fd4ab1a 100644 --- a/ecomp-c/asm-i386.c +++ b/ecomp-c/asm-i386.c @@ -49,6 +49,7 @@ * org 0x0000 * dd 0x0000 * db 0x00 + * db "abcd" */ /* constants */ @@ -57,6 +58,7 @@ enum { MAX_IDENT_LEN = 64, MAX_NUMBER_LEN = 10, MAX_HEXNUMBER_LEN = 8, + MAX_STRING_LEN = 64, MAX_PASSES = 10 }; @@ -74,6 +76,7 @@ typedef enum { S_org, S_ident, S_number, + S_string, S_colon, S_comma, S_lbrak, @@ -89,6 +92,7 @@ static char *symname[S_eof+1] = { "org", "ident", "number", + "string", ":", ",", "[", @@ -104,6 +108,7 @@ static S_Symbol sym; static char ident[MAX_IDENT_LEN+1]; static int num; +static char str[MAX_STRING_LEN+1]; static S_Symbol peek_sym = S_eof; @@ -144,6 +149,18 @@ static void *Allocate( unsigned int size ) return p; } +static char *AllocateAndCopyStr( char *s ) +{ + char *d; + int len = strlen( s ); + if( len > MAX_STRING_LEN ) { + Abort( "Too long string literal, should not happen" ); + } + d = (char *)Allocate( len + 1 ); + strlcpy( d, s, MAX_STRING_LEN ); + return d; +} + static int getChar( void ) { int c; @@ -233,16 +250,22 @@ static void hexnumber( void ) look = getChar( ); if( isHexDigit( look ) ) { - num = look - '0'; + if( isDigit( look ) ) { + num = look - '0'; + } else if( look >= 'a' && look <= 'f' ) { + num = 10 + look - 'a'; + } else { + num = 10 + look - 'A'; + } look = getChar( ); while( isHexDigit( look ) && n < MAX_HEXNUMBER_LEN ) { n++; if( isDigit( look ) ) { num = 16 * num + ( look - '0' ); } else if( look >= 'a' && look <= 'f' ) { - num = 16 * num + ( look - 'a' ); + num = 16 * num + ( 10 + look - 'a' ); } else { - num = 16 * num + ( look - 'A' ); + num = 16 * num + ( 10 + look - 'A' ); } look = getChar( ); } @@ -253,6 +276,28 @@ static void hexnumber( void ) } } +static void string( void ) +{ + int n = 0; + + if( look == '"' ) { + look = getChar( ); + while( ( isDigit( look ) || isAlpha( look ) || isSpecial( look ) ) && n < MAX_STRING_LEN ) { + str[n] = look; + n++; + look = getChar( ); + } + if( n == MAX_STRING_LEN ) { + Abort( "String exceeds maximal length" ); + } + str[n] = '\0'; + if( look != '\"' ) { + Abort( "Unterminated string literal" ); + } + look = getChar( ); + } +} + static void identifier( void ) { int n = 0; @@ -310,6 +355,10 @@ static S_Symbol getSym( void ) hexnumber( ); s = S_number; break; + case '\"': + string( ); + s = S_string; + break; case '0': case '1': case '2': @@ -443,6 +492,10 @@ static S_Symbol getSym( void ) case S_number: fprintf( stderr, "sym -> %s( '%d' )\n", symname[s], num ); break; + + case S_string: + fprintf( stderr, "sym -> %s( '%s' )\n", symname[s], str ); + break; default: fprintf( stderr, "sym -> %s\n", symname[s] ); @@ -673,6 +726,7 @@ static char *registername[5] = { typedef struct OperandInfo { OperandType type; int num; + char *str; Register reg; int addr; Symbol *symbol; @@ -835,6 +889,9 @@ static void free_opcode_info( OpcodeInfo *opcode_info ) ptr = opcode_info->operand; while( ptr != NULL ) { tmp = ptr->next; + if( ptr->str != NULL ) { + free( ptr->str ); + } free( ptr ); ptr = tmp; } @@ -882,6 +939,7 @@ static OperandInfo *parseOperand( void ) OperandInfo *operand_info; operand_info = Allocate( sizeof( OperandInfo ) ); + operand_info->str = NULL; operand_info->next = NULL; operand_info->addr = ADDRESS_UNDEFINED; operand_info->symbol = NULL; @@ -901,6 +959,10 @@ static OperandInfo *parseOperand( void ) operand_info->type = OPERAND_ABSOLUTE; operand_info->num = num; sym = getSym( ); + } else if( sym == S_string ) { + operand_info->type = OPERAND_ABSOLUTE; + operand_info->str = AllocateAndCopyStr( str ); + sym = getSym( ); } else if( sym == S_lbrak ) { /* pointer indirection as [a] */ Expect( S_lbrak ); @@ -1223,7 +1285,17 @@ static void print_opcodes( OpcodeInfo *opcode_info ) while( operand != NULL ) { switch( operand->type ) { case OPERAND_ABSOLUTE: - fprintf( stderr, "%s$%X", indent, operand->num ); + if( operand->str == NULL ) { + fprintf( stderr, "%s$%X", indent, operand->num ); + } else { + int i; + int len = strlen( operand->str ); + fprintf( stderr, "%s\"", indent ); + for( i = 0; i < len; i++ ) { + fprintf( stderr, "%c", operand->str[i] ); + } + fprintf( stderr, "\"" ); + } break; case OPERAND_REGISTER: fprintf( stderr, "%s%s", indent, registername[operand->reg] ); @@ -1385,7 +1457,15 @@ static void emit_opcode( OpcodeInfo *opcode_info ) Emit_double_little_endian( opcode_info->operand->num ); break; case OPCODE_PSEUDO_DB: - Emit_byte( opcode_info->operand->num ); + if( opcode_info->operand->str == NULL ) { + Emit_byte( opcode_info->operand->num ); + } else { + int i; + int len = strlen( opcode_info->operand->str ); + for( i = 0; i < len; i++ ) { + Emit( "%c", opcode_info->operand->str[i] ); + } + } break; case OPCODE_HLT: Emit( "%c", 0xF4 ); diff --git a/ecomp-c/tests/asm-i386/mov.asm b/ecomp-c/tests/asm-i386/mov.asm index 3be7224..7495e63 100644 --- a/ecomp-c/tests/asm-i386/mov.asm +++ b/ecomp-c/tests/asm-i386/mov.asm @@ -5,8 +5,9 @@ mov al, [flag1] mov eax, $ffffffff mov [flag2], al hlt -db 'XXXXXXX' +db "The" flag1: db $1 +db "Hello" flag2: db $2 -db 'XXXXXXX' +db "World" dd $01020304 |