Design ------ - one-pass: patching up addresses later or two-pass (scan location of all symbols first, have them ready for the second pass), two-pass assemblers are easier to write and relocation of addresses is possible in a deferred way, for instance at load time - intermediate listing-format - LC: location counter - extreme approach: encode the specific assembly language (e.g. register names) into the grammar, another extreme approach: hand-coded parser to parse the lines. One line == one instruction is something we usually don't like in a grammar ('\n' having meaning in the grammar), on the other hand keywords in assembly ('INSTR MOV AX, B END') looks a little bit clumpsy. Definitely when we have complex address calcualations we can benefit from a real parser (generated or not). - one vs. two-pass - labels and local labels (FUNC: and .loop and FUNC.loop) - LC-relative addressing $+5 Building -------- gcc -I../minilib -I../miniemu -g -O0 -m32 -march=i386 -ffreestanding -Werror -Wall -Wno-return-type -pedantic -std=c89 -o miniasm *.c ../minilib/*.c clang -I../minilib -I../miniemu -g -O0 -march=i386 -fno-builtin -std=c89 -Werror -Wall -Wno-return-type -o miniasm *.c ../minilib/*.c tcc -I../minilib -I../miniemu -g -O0 -march=i386 -fno-builtin -std=c89 -Werror -Wall -Wno-return-type -o miniasm *.c ../minilib/*.c pcc -I../minilib -I../miniemu -g -O0 -march=i386 -fno-builtin -std=c89 -Wall -Wno-return-type -o miniasm *.c ../minilib/*.c Usage ----- ./miniasm test1.asm ../miniemu/test1.bin ./miniasm test2.asm ../miniemu/test2.bin ./miniasm test3.asm ../miniemu/test3.bin ./miniasm test4.asm ../miniemu/test4.bin ./miniasm test5.asm ../miniemu/test5.bin ./miniasm test6.asm ../miniemu/test6.bin ./miniasm test7.asm ../miniemu/test7.bin ./miniasm test8.asm ../miniemu/test8.bin