summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2020-05-30 21:06:13 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2020-05-30 21:06:13 +0200
commit0307ad956911c1fbb526e002e2611f2037d986f2 (patch)
treef53d5be70f8d0683e6bf8500bfc408d49de82206
parentde5d9c5d1b735e95a20a8671d38697f1c7e638ea (diff)
downloadcompilertests-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.c90
-rw-r--r--ecomp-c/tests/asm-i386/mov.asm5
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