From 90689d22cccce853ab6cb7dd078baaa501afb777 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 26 Sep 2021 20:31:51 +0200 Subject: cc: - fixed zeroing of EDX before division if operating register was EAX - implemented simple itoa in assembly in putint operation --- miniany/README | 4 +++ miniany/cc.c | 101 +++++++++++++++++++++++++++++++++++++++++++------------- miniany/test1.c | 3 +- 3 files changed, 84 insertions(+), 24 deletions(-) diff --git a/miniany/README b/miniany/README index 033f3d4..6367011 100644 --- a/miniany/README +++ b/miniany/README @@ -73,6 +73,10 @@ complex things into our own compiler. * https://github.com/lotabout/write-a-C-interpreter/blob/master/tutorial/en/: tutorial based on C4 how to build a C interpreter, explains nicely details in C4. +* https://github.com/felipensp/assembly/blob/master/x86/itoa.s, + https://baptiste-wicht.com/posts/2011/11/print-strings-integers-intel-assembly.html, + putint for early debugging + * documentation * "Compiler Construction", Niklaus Wirth * https://github.com/DoctorWkt/acwj: a nice series on building a C compiler, diff --git a/miniany/cc.c b/miniany/cc.c index b9cfe5a..acba6df 100644 --- a/miniany/cc.c +++ b/miniany/cc.c @@ -702,6 +702,11 @@ int genDiv( struct Generator *generator, int leftreg, int rightreg ) int reg; if( leftreg == EAX ) { + if( !generator->regFree[EDX] ) { + genSaveReg( generator, EDX ); + } + putstring( "mov edx, 0" ); + putnl( ); reg = genBinary( "div", generator, leftreg, rightreg, 1 ); } else { if( !generator->regFree[EAX] ) { @@ -795,34 +800,85 @@ void genPrologue( struct Compiler *compiler ) putstring( "format binary" ); putnl( ); putstring( "use32" ); putnl( ); putstring( "org $1000000" ); putnl( ); - putstring( "jmp _start" ); putnl( ); + putstring( "jmp _start" ); putnl( ); putstring( "putint:" ); putnl( ); + putstring( "mov esi, 0xa" ); putnl( ); + putstring( "lea edi, [putint_string_fmt]" ); putnl( ); + putstring( "add edi, 9" ); putnl( ); + putstring( "itoa_loop:" ); putnl( ); + putstring( "mov edx, 0" ); putnl( ); + putstring( "div esi" ); putnl( ); + putstring( "add edx, 0x30" ); putnl( ); + putstring( "mov byte [edi], dl" ); putnl( ); + putstring( "dec edi" ); putnl( ); + putstring( "cmp eax, 0" ); putnl( ); + putstring( "jnz itoa_loop" ); putnl( ); putstring( "mov eax, 4" ); putnl( ); putstring( "mov ebx, 1" ); putnl( ); /* TODO: itoa in assembly (yuck!) and print resulting string */ - putstring( "mov ecx, putint_string" ); putnl( ); + putstring( "mov ecx, putint_string_fmt" ); putnl( ); /* TODO: compute length with a assemble time function sizeof or so.. */ - putstring( "mov edx, 13" ); putnl( ); + putstring( "mov edx, 11" ); putnl( ); putstring( "int 0x80" ); putnl( ); - putstring( "ret 4" ); putnl( ); + putstring( "ret" ); putnl( ); putstring( "_start:" ); putnl( ); - + /* - __asm__ volatile( "\ - push %%ebx\n\ - push %%ecx\n\ - push %%edx\n\ - mov %1, %%eax\n\ - mov %2, %%ebx\n\ - mov %3, %%ecx\n\ - mov %4, %%edx\n\ - int $0x80\n\ - mov %%eax, %0\n\ - pop %%edx\n\ - pop %%ecx\n\ - pop %%ebx\n" : "=m"( retval ) : "m"( id ), "m"( arg0 ), "m"( arg1 ), "m"( arg2 ) - : "eax", "ebx", "ecx", "edx" ); - */ + +fmt: .string "%s\n" + +.lcomm converted, 10 + + + .section .text + +.global _start + +_start: + + xorl %ecx, %ecx + xorl %edi, %edi + movl $NUMBER, %eax + +itoa_loop: + # Limpa para divisão + xorl %edx, %edx + + movl $10, %esi + + # Agora nós temos o quociente em %eax + # e o resto da divisão em %edx + idiv %esi + + # Convertendo para a representação em ASCII + addl $48, %edx + + pushl %edx + incl %ecx + + xorl $0, %eax + jnz itoa_loop + +rev_loop: + popl %eax + movl %eax, converted(, %edi, 1) + incl %edi + decl %ecx + + cmpl $0, %ecx + jnz rev_loop + + pusha + pushl $converted + pushl $fmt + call printf + addl $8, %esp + popa + + # Exiting + movl $1, %eax + int $0x80 + */ } void genEpilogue( struct Compiler *compiler ) @@ -836,8 +892,8 @@ void genEpilogue( struct Compiler *compiler ) genAddGlob( compiler->generator, sym->name ); sym = sym->next; } - putstring( "putint_string:" ); putnl( ); - putstring( "db \"putint test \", 10, 0" ); putnl( ); + putstring( "putint_string_fmt:" ); putnl( ); + putstring( "db \" \", 10, 0" ); putnl( ); } /* parser */ @@ -1049,7 +1105,6 @@ void parsePutint( struct Compiler *compiler ) node = parseExpression( parser, 0 ); parserExpect( parser, S_SEMICOLON, ";" ); generateFromAST( compiler->generator, node, NOREG ); - putstring( "push eax" ); putnl( ); putstring( "call putint" ); putnl( ); genFreeAllRegs( compiler->generator ); freeASTnode( node ); diff --git a/miniany/test1.c b/miniany/test1.c index d7015e2..707ff16 100644 --- a/miniany/test1.c +++ b/miniany/test1.c @@ -4,5 +4,6 @@ int i; int j; i = 12+25/5-2*3; // 25/5 -> 5, 12+5 -> 17, 2*3 -> 6, 17-6 -> 11 -j = i/3+3*4; // 11 / 3 -> 3, 3*4 -> 12, 3+12 -> 15 putint i; +j = i/3+3*4; // 11 / 3 -> 3, 3*4 -> 12, 3+12 -> 15 +putint j; -- cgit v1.2.3-54-g00ecf