|  | Suppose I'm copying data about x86-64 opcodes per instruction signature out of the amd64 programmer's manual: http://support.amd.com/us/Processor_TechDocs/APM_V3_24594.pdf and into a text file: http://pastebin.com/raw.php?i=TrGLRRMy Much of this crap is repetitive.  In particular, many instructions will have the same opcode for their 16-bit, 32-bit, and 64-bit forms (they will be distinguished in code by a prefix indicating the operand size): And many of them (usually the same ones) operate on "reg/mem16, imm16", "reg/mem32, imm32", and "reg/mem64, imm32".  Also for the ADD instruction, but in the highly abbreviated form I settled on:  ADD:
  reg/mem16, reg16 -> 01 /r
  reg/mem32, reg32 -> 01 /r
  reg/mem64, reg64 -> 01 /r
 Even with these abbrevs, it's painful to type that up manually for more than one or two instructions.  So, I wrote progressively more advanced Arc functions to do much of it for me.  It began with a simple function that would generate three things and put them into the clipboard:  r16 i16 . 81 /0 iw
  r32 i32 . 81 /0 id
  r64 i32 . 81 /0 id
 Note that the "i64" there is wrong; it should be "i32".  I corrected that by hand, but eventually decided to automate it.  I moved from a "prn"-based command to a token-based symbol replacement thing, so that instead of (prn "rm" n) where n was 16/32/64, I'd write the symbol 'rmn, which would get replaced by "rm16"/"rm32"/"rm64"; the 'in symbol would be replaced by "i16"/"i32"/"i32".  By the end, I had a kind of "interpreter" that handled many "commands".  Also, of course, I had a wrapping macro so I didn't have to quote anything.  arc> (def dick (a b c) (pbcopy:tostring:map (fn (x y) (prn a x
  " " b x " . " c " " y)) '(16 32 64) '(iw id id)))
  #<procedure: dick>
  arc> (dick "rm" "i" "83 /4")
  -->
  rm16 i16 . 83 /4 iw
  rm32 i32 . 83 /4 id
  rm64 i64 . 83 /4 id
 And finally I ran it as a "read-eval-pbcopy loop", so that I didn't have to type the "(d4 ...)" part (or edit a previous command).  (def dick4 (xs) ;note that this was all on one line in the REPL
    (mapn (fn (n)
            (withs (a (expt 2 (+ n 4)) b (if (is a 64) 32 a))
              (apply prsn
                     (map [case _
                            in (symb 'i b)
                            rn (symb 'r a)
                            rmn (symb 'rm a)
                            mn (symb 'm a)
                            w ('(iw id id) n)
                            x "."
                            +rx ('(+rw +rd +rq) n)
                            ax ('(ax eax rax) n)
                            _]
                          xs))))
          0 2))
  (mac d4 args `(pbcopy:tostring:dick4 ',args))
  arc> (d4 rn rmn in x 69 /r w)
  -->
  r16 rm16 i16 . 69 /r iw
  r32 rm32 i32 . 69 /r id
  r64 rm64 i32 . 69 /r id
 Also, I wrote a specialized command to generate all of the conditional move instructions (cmovxx), and modified it to handle the conditional jumps (jxx) and sets (setx).  arc> (while t (eval `(d4 ,@(readall:readline))))
  rn rmn x 2B /r
  ax in x A9 w
  rmn in x F7 /0 w
 You can view the whole Arc log here: (For some reason, my terminal sometimes drops newlines.) http://pastebin.com/raw.php?i=Qr9n6A71 Anyway, having an Arc REPL made this task easier, faster, and much more pleasant.  Thus, I am thankful for it. Now everyone have a happy Thanksgiving, made more convenient by tools made by others and yourself and by your expertise with them. (Why was I putting opcodes into a mostly machine-readable format in the first place?  You may consider this a teaser of things to come.) |