From 33a4671260b567173c2c931992cd096513f4b9ca Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Thu, 23 Jul 2020 17:28:43 +0200 Subject: parsing $ and $$ in asm-i386 - freestanding libc: added ungetc function with one pushback character - asm-i386: for now adding $ and $$ as special addresses to the operands in the expression tree --- ecomp-c/asm-i386.c | 49 ++++++++++++++++++++++++++++++++++-------- ecomp-c/libc-freestanding.c | 16 +++++++++++++- ecomp-c/tests/asm-i386/elf.asm | 3 +++ 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/ecomp-c/asm-i386.c b/ecomp-c/asm-i386.c index 3cb6ff1..a0a65a7 100644 --- a/ecomp-c/asm-i386.c +++ b/ecomp-c/asm-i386.c @@ -70,8 +70,8 @@ enum { }; static int DEBUG_GETCHAR = 0; -static int DEBUG_SCANNER = 1; -static int DEBUG_PARSER = 1; +static int DEBUG_SCANNER = 0; +static int DEBUG_PARSER = 0; /* scanner */ @@ -92,6 +92,8 @@ typedef enum { S_minus, S_star, S_slash, + S_current_org, + S_current_addr, S_eof } S_Symbol; @@ -112,6 +114,8 @@ static char *symname[S_eof+1] = { "-", "*", "/", + "$$", + "$", "eof" }; @@ -203,6 +207,11 @@ static int getChar( void ) return c; } +static void ungetChar( int c ) +{ + ungetc( c, stdin ); +} + static int isWhite( int c ) { if( c == ' ' || c == '\r' || c == '\t' ) return 1; @@ -373,8 +382,18 @@ static S_Symbol getSym( void ) s = S_newline; break; case '$': - hexnumber( ); - s = S_number; + look = getChar( ); + if( look == '$' ) { + s = S_current_org; + } else if( ( look >= '0' && look <= '9' ) || + ( look >= 'a' && look <= 'f' ) || + ( look >= 'A' && look <= 'F' ) ) { + ungetChar( look ); + s = S_number; + hexnumber( ); + } else { + s = S_current_addr; + } break; case '\"': string( ); @@ -612,7 +631,9 @@ typedef struct Symbol { struct Symbol *symbol = NULL; enum { - ADDRESS_UNDEFINED = 0x7FFFFFFF + ADDRESS_UNDEFINED = 0x7FFFFFFF, + ADDRESS_CURRENT_ORG = 0x7FFFFFFE, + ADDRESS_CURRENT_ADDR = 0x7FFFFFFD }; static Symbol *get_symbol( char *name ) @@ -1060,7 +1081,17 @@ static ExpressionNode *parseFactor( void ) node = create_expression_node( ); node->type = EXPRESSION_NODE_TYPE_VAR; node->symbol = symbol; - sym = getSym( ); + sym = getSym( ); + } else if( sym == S_current_org ) { + node = create_expression_node( ); + node->type = EXPRESSION_NODE_TYPE_CONST; + node->integer_value = ADDRESS_CURRENT_ORG; + sym = getSym( ); + } else if( sym == S_current_addr ) { + node = create_expression_node( ); + node->type = EXPRESSION_NODE_TYPE_CONST; + node->integer_value = ADDRESS_CURRENT_ADDR; + sym = getSym( ); } else { Abort( "Expected a literal, a variable or a constant." ); } @@ -1105,7 +1136,7 @@ static ExpressionNode *parseExpression( void ) return node; } -static int evaluate_const_expression_as_integer( ExpressionNode *node ) +static int evaluateExpression( ExpressionNode *node ) { switch( node->type ) { case EXPRESSION_NODE_TYPE_CONST: @@ -1138,13 +1169,13 @@ static OperandInfo *parseOperand( OpcodeInfo *opcode_info ) assign_label( operand_info, ident ); } sym = getSym( ); - } else if( sym == S_number ) { + } else if( sym == S_number || sym == S_current_org || sym == S_current_addr ) { /* absolute operand, like in mov eax, $1, * we have assemble-time expressions here */ operand_info->type = OPERAND_ABSOLUTE; operand_info->node = parseExpression( ); - operand_info->num = evaluate_const_expression_as_integer( operand_info->node ); + operand_info->num = evaluateExpression( operand_info->node ); free_expression_node( operand_info->node ); } else if( sym == S_string ) { operand_info->type = OPERAND_ABSOLUTE; diff --git a/ecomp-c/libc-freestanding.c b/ecomp-c/libc-freestanding.c index ca41ae7..f37aa83 100644 --- a/ecomp-c/libc-freestanding.c +++ b/ecomp-c/libc-freestanding.c @@ -399,9 +399,10 @@ typedef struct { int readpos; int size; char buf[INTERNAL_STDIO_BUFSIZE]; + int pushback; } FILE; -static FILE fds[3] = { { STDIN_FILENO, 0, 0, "" }, { STDOUT_FILENO, 0, 0, "" }, { STDERR_FILENO, 0, 0, "" } }; +static FILE fds[3] = { { STDIN_FILENO, 0, 0, "", 0 }, { STDOUT_FILENO, 0, 0, "", 0 }, { STDERR_FILENO, 0, 0, "", 0 } }; FILE *stdin = &fds[0]; FILE *stdout = &fds[1]; @@ -586,6 +587,12 @@ int fgetc( FILE *stream ) { int c; + if( stream->pushback != 0 ) { + c = stream->pushback; + stream->pushback = 0; + return c; + } + if( stream->size == 0 ) { int n = read_string( stream->fileno, stream->buf, INTERNAL_STDIO_BUFSIZE ); if( n < 0 ) { @@ -606,6 +613,13 @@ int fgetc( FILE *stream ) return c; } +int ungetc( int c, FILE *stream ) +{ + stream->pushback = c; + + return c; +} + int getchar( void ) { return fgetc( stdin ); diff --git a/ecomp-c/tests/asm-i386/elf.asm b/ecomp-c/tests/asm-i386/elf.asm index e23f61d..3fba61e 100644 --- a/ecomp-c/tests/asm-i386/elf.asm +++ b/ecomp-c/tests/asm-i386/elf.asm @@ -2,6 +2,9 @@ format binary use32 org $08048000 ehdr: +mov eax, $$ +mov ebx, $ +mov ecx, $1 db $7F, "ELF" ; e_ident: magic db 1 ; EI_CLASS: ELFCLASS32 db 1 ; EI_BYTE: ELFDATA2LSB (little endian, 2's complement) -- cgit v1.2.3-54-g00ecf