项目作者: damiik

项目描述 :
my assembler experiment in Ocaml
高级语言: OCaml
项目地址: git://github.com/damiik/asm.git
创建时间: 2021-01-19T12:26:24Z
项目社区:https://github.com/damiik/asm

开源协议:

下载


asm

This is my experimental assembler for 6502 processor in Ocaml with monadic parser described here: https://www.cs.nott.ac.uk/~pszgmh/monparsing.pdf.


This program was mainly inspired by Tsoding parcoom parser: https://github.com/tsoding/parcoom



As input to parser I used tokens from lexer (instead of string) and this simple solution lets me to forget about whitespaces and comments in parser grammar.


Now assembling is processed in 3 passes: pre-processing parse with directives calculations (preprocess), parsing tokens and generating instructions (by asmparser) and post-process with calculating labels relative and absolute positions in code (by asmparser).


testing with utop:

  • dune test

    executing main

  • dune exec asm

    with utop:

    • utop>> #load "str.cma";;
    • utop>> #use "./asmparser.ml";;
    • utop>> exp_p.run {tokens= ref (Array.of_list (tokenize "1203*2+5*10 ss")) ; pos= 0};;
    • utop>> exp_p.run {tokens= ref (Array.of_list (tokenize "(2+(5*3))-8")) ; pos= 0};;
    • utop>> exp_p.run {tokens= ref (Array.of_list (tokenize "2+5*-(-%0001001010+3)-8")) ; pos= 0};;

with dune & utop:

  • dune utop ./lib
  • utop>> #use "./lib/asmparser.ml";;
  • utop>> #use "./lib/preprocess/preprocess.ml";;
  • utop>>

    1. {|
    2. .org $8000
    3. .equ Char1 'A'
    4. Char2 = ('A' + 1)
    5. l0: JMP (l1)
    6. LDA heart, X
    7. CMP #Char1 + 1
    8. BNE l1
    9. CMP #Char2
    10. LDA $A0, X
    11. l1: JMP l0
    12. heart: .byte %00000, %01010, %11111
    13. |} |> tokenize |> preprocess_tokens |> asm_lines_p.run;;

Output:

  1. ...
  2. >>>success
  3. - : state * (asm_line list, string) result =
  4. ({tokens =
  5. {contents =
  6. [|Tok_NewL; Tok_Label "l0:"; Tok_Word "JMP"; Tok_LParen; Tok_Word "l1";
  7. Tok_RParen; Tok_NewL; Tok_Word "LDA"; Tok_Word "heart"; Tok_Coma;
  8. Tok_Word "X"; Tok_NewL; Tok_Word "CMP"; Tok_Hash; Tok_Number "65";
  9. Tok_Sum; Tok_Number "1"; Tok_NewL; Tok_Word "BNE"; Tok_Word "l1";
  10. Tok_NewL; Tok_Word "CMP"; Tok_Hash; Tok_Number "66"; Tok_NewL;
  11. Tok_Word "LDA"; Tok_Number "$A0"; Tok_Coma; Tok_Word "X"; Tok_NewL;
  12. Tok_Label "l1:"; Tok_Word "JMP"; Tok_Word "l0"; Tok_NewL;
  13. Tok_Label "heart:"; Tok_Direct ".byte"; Tok_Number "%00000"; Tok_Coma;
  14. Tok_Number "%01010"; Tok_Coma; Tok_Number "%11111"; Tok_NewL; Tok_End|]};
  15. token_ix = 42; byte_counter = 32788; identifiers = [];
  16. labels =
  17. [{name = "heart:"; value = 32785}; {name = "l1:"; value = 32782};
  18. {name = "l0:"; value = 32768}]},
  19. Ok
  20. [Empty; Instr {opcode = 108; operand = Fixed [14; 128]};
  21. Instr {opcode = 189; operand = Fixed [17; 128]};
  22. Instr {opcode = 201; operand = Fixed [66]};
  23. Instr {opcode = 208; operand = Fixed [4]};
  24. Instr {opcode = 201; operand = Fixed [66]};
  25. Instr {opcode = 181; operand = Fixed [160]};
  26. Instr {opcode = 76; operand = Fixed [0; 128]};
  27. Label_Data ("heart:", 32785, [0; 10; 31])])