comptut
changeset 0:10f07b308aab tutor2
tutor2.txt completed
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 15 Mar 2015 05:47:44 +0200 |
parents | |
children | d872095206bf |
files | .hgignore COMPILE Makefile RUN src/main.c |
diffstat | 5 files changed, 255 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Sun Mar 15 05:47:44 2015 +0200 1.3 @@ -0,0 +1,5 @@ 1.4 +\.o$ 1.5 +\.s$ 1.6 +\.swp$ 1.7 +^test$ 1.8 +^a\.out$
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/COMPILE Sun Mar 15 05:47:44 2015 +0200 2.3 @@ -0,0 +1,5 @@ 2.4 +#!/bin/sh 2.5 + 2.6 +./test >out.s && \ 2.7 + as --32 -o out.o out.s && \ 2.8 + ld -m elf_i386 out.o
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/Makefile Sun Mar 15 05:47:44 2015 +0200 3.3 @@ -0,0 +1,12 @@ 3.4 +src = $(wildcard src/*.c) 3.5 +obj = $(src:.c=.o) 3.6 +bin = test 3.7 + 3.8 +CFLAGS = -pedantic -Wall -g 3.9 + 3.10 +$(bin): $(obj) 3.11 + $(CC) -o $@ $(obj) $(LDFLAGS) 3.12 + 3.13 +.PHONY: clean 3.14 +clean: 3.15 + rm -f $(obj) $(bin)
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/RUN Sun Mar 15 05:47:44 2015 +0200 4.3 @@ -0,0 +1,3 @@ 4.4 +#!/bin/sh 4.5 + 4.6 +./a.out; echo $?
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/main.c Sun Mar 15 05:47:44 2015 +0200 5.3 @@ -0,0 +1,230 @@ 5.4 +#include <stdio.h> 5.5 +#include <stdlib.h> 5.6 +#include <ctype.h> 5.7 +#include <stdarg.h> 5.8 + 5.9 +void init(void); 5.10 +void expression(void); 5.11 +void term(void); 5.12 +void factor(void); 5.13 +void add(void); 5.14 +void sub(void); 5.15 +void mul(void); 5.16 +void divide(void); 5.17 +void get_char(void); 5.18 +void match(char c); 5.19 +char get_name(void); 5.20 +char get_num(void); 5.21 +void stop(const char *s, ...); 5.22 +void expected(const char *s); 5.23 +void emit(const char *fmt, ...); 5.24 +void vemit(const char *fmt, va_list ap); 5.25 +void emitln(const char *fmt, ...); 5.26 +int is_addsub(char c); 5.27 + 5.28 +FILE *infile, *outfile; 5.29 +char look; 5.30 + 5.31 +static const char *prologue = 5.32 + "\t.globl _start\n" 5.33 + "_start:\n" 5.34 + "\tcall main\n" 5.35 + "\tmov %eax, %ebx\n" 5.36 + "\tmov $1, %eax\n" 5.37 + "\tint $0x80\n" 5.38 + "main:\n" 5.39 + "\t# ---- START ----\n"; 5.40 + 5.41 +static const char *epilogue = "\t# ---- END ----\n\tret\n"; 5.42 + 5.43 +int main(void) 5.44 +{ 5.45 + infile = stdin; 5.46 + outfile = stdout; 5.47 + 5.48 + init(); 5.49 + /* output prologue */ 5.50 + fputs(prologue, outfile); 5.51 + 5.52 + expression(); 5.53 + 5.54 + /* output epilogue */ 5.55 + fputs(epilogue, outfile); 5.56 + return 0; 5.57 +} 5.58 + 5.59 +void init(void) 5.60 +{ 5.61 + get_char(); 5.62 +} 5.63 + 5.64 +void expression(void) 5.65 +{ 5.66 + if(is_addsub(look)) { 5.67 + emitln("xor %%eax, %%eax"); 5.68 + } else { 5.69 + term(); 5.70 + } 5.71 + 5.72 + while(is_addsub(look)) { 5.73 + emitln("push %%eax"); 5.74 + switch(look) { 5.75 + case '+': 5.76 + add(); 5.77 + break; 5.78 + case '-': 5.79 + sub(); 5.80 + break; 5.81 + default: 5.82 + expected("addop"); 5.83 + } 5.84 + } 5.85 +} 5.86 + 5.87 +void term(void) 5.88 +{ 5.89 + factor(); 5.90 + while(look == '*' || look == '/') { 5.91 + emitln("push %%eax"); 5.92 + switch(look) { 5.93 + case '*': 5.94 + mul(); 5.95 + break; 5.96 + case '/': 5.97 + divide(); 5.98 + break; 5.99 + default: 5.100 + expected("mulop"); 5.101 + } 5.102 + } 5.103 +} 5.104 + 5.105 +void factor(void) 5.106 +{ 5.107 + if(look == '(') { 5.108 + match('('); 5.109 + expression(); 5.110 + match(')'); 5.111 + } else { 5.112 + emitln("mov $%c, %%eax", get_num()); 5.113 + } 5.114 +} 5.115 + 5.116 +void add(void) 5.117 +{ 5.118 + match('+'); 5.119 + term(); 5.120 + emitln("pop %%ebx"); 5.121 + emitln("add %%ebx, %%eax"); 5.122 +} 5.123 + 5.124 +void sub(void) 5.125 +{ 5.126 + match('-'); 5.127 + term(); 5.128 + emitln("pop %%ebx"); 5.129 + emitln("sub %%ebx, %%eax"); 5.130 + emitln("neg %%eax"); 5.131 +} 5.132 + 5.133 +void mul(void) 5.134 +{ 5.135 + match('*'); 5.136 + factor(); 5.137 + emitln("pop %%ebx"); 5.138 + emitln("imul %%ebx"); 5.139 +} 5.140 + 5.141 +void divide(void) 5.142 +{ 5.143 + match('/'); 5.144 + factor(); 5.145 + emitln("mov %%eax, %%ebx"); 5.146 + emitln("pop %%eax"); 5.147 + emitln("idiv %%ebx"); 5.148 +} 5.149 + 5.150 +void get_char(void) 5.151 +{ 5.152 + look = fgetc(infile); 5.153 +} 5.154 + 5.155 +void match(char c) 5.156 +{ 5.157 + if(look == c) { 5.158 + get_char(); 5.159 + } else { 5.160 + char s[2] = {0, 0}; 5.161 + s[0] = c; 5.162 + expected(s); 5.163 + } 5.164 +} 5.165 + 5.166 +char get_name(void) 5.167 +{ 5.168 + char res; 5.169 + if(!isalpha(look)) { 5.170 + expected("name"); 5.171 + } 5.172 + res = toupper(look); 5.173 + get_char(); 5.174 + return res; 5.175 +} 5.176 + 5.177 +char get_num(void) 5.178 +{ 5.179 + char res; 5.180 + if(!isdigit(look)) { 5.181 + expected("integer"); 5.182 + } 5.183 + res = look; 5.184 + get_char(); 5.185 + return res; 5.186 +} 5.187 + 5.188 +void stop(const char *s, ...) 5.189 +{ 5.190 + va_list ap; 5.191 + 5.192 + fprintf(stderr, "error: "); 5.193 + va_start(ap, s); 5.194 + vfprintf(stderr, s, ap); 5.195 + va_end(ap); 5.196 + fputc('\n', stderr); 5.197 + 5.198 + abort(); 5.199 +} 5.200 + 5.201 +void expected(const char *s) 5.202 +{ 5.203 + stop("%s expected", s); 5.204 +} 5.205 + 5.206 +void emit(const char *fmt, ...) 5.207 +{ 5.208 + va_list ap; 5.209 + va_start(ap, fmt); 5.210 + vemit(fmt, ap); 5.211 + va_end(ap); 5.212 +} 5.213 + 5.214 +void vemit(const char *fmt, va_list ap) 5.215 +{ 5.216 + fputc('\t', outfile); 5.217 + vfprintf(outfile, fmt, ap); 5.218 +} 5.219 + 5.220 +void emitln(const char *fmt, ...) 5.221 +{ 5.222 + va_list ap; 5.223 + va_start(ap, fmt); 5.224 + vemit(fmt, ap); 5.225 + va_end(ap); 5.226 + fputc('\n', outfile); 5.227 +} 5.228 + 5.229 + 5.230 +int is_addsub(char c) 5.231 +{ 5.232 + return c == '+' || c == '-'; 5.233 +}