datatype Operand = (* size (in bytes) segment offset base index scale *)
Mem of ( int * stringoption * int * string * string * int)
| Reg ofstring
| Imm of LargeInt.int
fun pp_instr (Instr (a,si,m,op1,op2,op3)) =
LargeInt.toString a ^ ": " ^ m ^ " " ^ pp_operands [op1,op2,op3] ^ " (" ^ LargeInt.toString si ^ ")"
val intFromHexString = StringCvt.scanString (LargeInt.scan StringCvt.HEX) o Substring.string
fun intFromHexString_forced s = case intFromHexString s of
SOME i => i
| NONE => raise Fail ("Could not convert string '" ^ Substring.string s ^ "' to int.")
fun is_whitespace c = (c = #" " orelse c = #"\t" orelse c = #"\n")
fun trim str = letval (_,x) = Substring.splitl is_whitespace str val (y,_) = Substring.splitr is_whitespace x in
y end;
fun overwrite_str "" s = s
| overwrite_str s "" = s
| overwrite_str _ s = s
fun overwrite_str_option NONE s = s
| overwrite_str_option s NONE = s
| overwrite_str_option _ s = s
fun max x y = if x >= y then x else y
fun overwrite_Mem (Mem (si,seg,off,base,ind,sc)) (Mem (si',seg',off',base',ind',sc')) =
Mem (max si si',overwrite_str_option seg seg',max off off',overwrite_str base base',overwrite_str ind ind',max sc sc')
fun parse_operand_address_between_brackets_inner str = if is_register str then
Mem (0,NONE,0,Substring.string str,"",0) (* base *) else letval tokens = map trim (Substring.tokens (fn c => c = #"*") str) in if length tokens = 1then case intFromHexString str of
SOME i => Mem (0,NONE,i,"","",0) (* offset *)
| NONE => raise Fail ("Don't know how to parse operand part:" ^ Substring.string str) elseif length tokens = 2then if is_register (nth tokens 0) then
Mem (0,NONE,0,"",Substring.string (nth tokens 0),intFromHexString_forced (nth tokens 1)) (* index * scale *) elseif is_register (nth tokens 1) then
Mem (0,NONE,0,"",Substring.string (nth tokens 1),intFromHexString_forced (nth tokens 0)) (* scale * index *) else raise Fail ("Don't know how to parse operand part:" ^ Substring.string str) else raise Fail ("Don't know how to parse operand part:" ^ Substring.string str) end
fun parse_operand_address_between_brackets_sum si segment_reg str = letval tokens = map trim (Substring.tokens (fn c => c = #"+") str) in
fold (overwrite_Mem o parse_operand_address_between_brackets_inner)
tokens
(Mem (si,segment_reg ,0,"","",0)) end;
fun parse_operand_address_between_brackets_sub si segment_reg str = letval (lhs,num) = Substring.splitl (fn c => c <> #"-") str; val (Mem (x0,x1,_,x3,x4,x5)) = parse_operand_address_between_brackets_sum si segment_reg lhs in
Mem (x0,x1,intFromHexString_forced num,x3,x4,x5) end
fun parse_operand_address_between_brackets si segment_reg str = letval (_,num) = Substring.splitl (fn c => c <> #"-") str in ifSubstring.isEmpty num then
parse_operand_address_between_brackets_sum si segment_reg str else
parse_operand_address_between_brackets_sub si segment_reg str end
fun skip_brackets str = letval (x,y) = Substring.splitAt (trim str,1) val (z,_) = Substring.splitl (fn c => c <> #"]") y in ifSubstring.compare (x,Substring.full "[") = EQUAL then
z else raise Fail ("Expecting non-empty bracketed string preceded with colon or an immediate in hex-format, but got: " ^ Substring.string str) end;
fun parse_operand_address_bracketed si segment_reg str = case intFromHexString str of
SOME imm => Mem (si,segment_reg,imm,"", "",0)
| NONE => parse_operand_address_between_brackets si segment_reg (skip_brackets str)
fun tail str = caseSubstring.getc str of
NONE => raise Fail ("Expecting non-empty string, but got: " ^ Substring.string str)
| SOME (_,s) => s;
fun parse_operand_address si str = caseSubstring.splitl (fn c => c <> #":") str of
(before_colon, after_colon) => ifSubstring.isEmpty after_colon then
parse_operand_address_bracketed si NONE before_colon else
parse_operand_address_bracketed si (SOME (Substring.string (trim before_colon))) (tail after_colon);
fun parse_operand str' = letval str = trim str' in ifSubstring.isPrefix "BYTE PTR" str then
parse_operand_address 1 (snd (Substring.splitAt (str,8))) elseifSubstring.isPrefix "WORD PTR" str then
parse_operand_address 2 (snd (Substring.splitAt (str,8))) elseifSubstring.isPrefix "DWORD PTR" str then
parse_operand_address 4 (snd (Substring.splitAt (str,9))) elseifSubstring.isPrefix "QWORD PTR" str then
parse_operand_address 8 (snd (Substring.splitAt (str,9))) elseifSubstring.isPrefix "XMMWORD PTR" str then
parse_operand_address 16 (snd (Substring.splitAt (str,11))) elseifSubstring.isPrefix "[" str then(* happens in case of a LEA instruction *)
parse_operand_address 0 str elseifList.find (fn (str') => string_ord (Substring.string str,str') = EQUAL) registers <> NONE then
Reg (Substring.string str) else case intFromHexString str of
NONE => raise Fail ("Cannot read hex number in string: " ^ (Substring.string str))
| SOME imm => Imm imm end;
fun parse_operands str = letval tokens = map trim (Substring.tokens (fn c => c = #",") (trim str)) val ops = map parse_operand tokens in case ops of
[] => (NONE,NONE,NONE)
| [op1] => (SOME op1,NONE,NONE)
| [op1,op2] => (SOME op1,SOME op2,NONE)
| [op1,op2,op3] => (SOME op1,SOME op2,SOME op3)
| _ => raise Fail ("Unexpected number of operands in : " ^ Substring.string str) end;
fun remove_comment str = letval (str0,str1) = Substring.splitl (fn c => c <> #"#" andalso c <> #"<") str in ifSubstring.isEmpty str1 then str0 elseSubstring.trimr 1 str0 end
fun parse_external_func a si str = letval (m,func) = Substring.splitl (fn c => c <> #" ") str val func_name = Substring.string (trim func) in
Instr (a, si, Substring.string m, SOME (Reg func_name), NONE, NONE) end
fun parse_normal_instr a si str = letval (_,rem1) = Substring.splitl (fn c => c = #":" orelse c = #" ") str val (m,rem2) = Substring.splitl (fn c => c <> #" ") rem1 val (op1,op2,op3) = parse_operands rem2 in
Instr (a, si, Substring.string m, op1,op2,op3) end;
fun parse_instr si str = letval str' = remove_comment (Substring.full str) val (addr,rem0) = Substring.splitl (fn c => c <> #":") str' val a = intFromHexString_forced (Substring.full ("0x" ^ Substring.string (trim addr))) in ifSubstring.isPrefix "EXTERNAL_FUNCTION" (trim (tail (rem0))) then
parse_external_func a si (trim (tail (rem0))) else
parse_normal_instr a si rem0 end;
fun read_instr_addr str = letval instr = parse_instr 0 str val (Instr (a,_,_,_,_,_)) = instr in
a end
(* EMBEDDING INTO HOL *)
val mk_nat = HOLogic.mk_number @{typ nat} val mk_string = HOLogic.mk_string fun mk_word_typ_from_num s = Syntax.read_typ @{context} ("num \<Rightarrow> " ^ Int.toString s ^ " word") fun mk_word_typ s = Syntax.read_typ @{context} (Int.toString s ^ " word")
fun mk_word i b = if i=0then Const ("Groups.zero_class.zero", mk_word_typ b) elseif i=1then Const ("Groups.one_class.one", mk_word_typ b) elseif i < 0then
Syntax.read_term @{context} ("uminus :: " ^ Int.toString b ^ " word \<Rightarrow> " ^ Int.toString b ^ " word")
$ (Const ("Num.numeral_class.numeral", mk_word_typ_from_num b) $ HOLogic.mk_numeral (0 - i)) else Const ("Num.numeral_class.numeral", mk_word_typ_from_num b) $ HOLogic.mk_numeral i
fun mk_instr (Instr (_,_,"EXTERNAL_FUNCTION",SOME (Reg f),NONE,NONE)) lthy = letval def = Syntax.read_term (Local_Theory.target_of lthy) ("EXTERNAL_FUNCTION_" ^ f) in if fastype_of def = (@{typ state} --> @{typ state}) then
@{term ExternalFunc} $ def else raise Fail ("Unknown external function: " ^ f ^ "; expecting a function named EXTERNAL_FUNCTION_" ^ f ^ " in locale unknowns of type state \<Rightarrow> state") end
| mk_instr (Instr (a,si,m,op1,op2,op3)) _ =
@{term Instr} $ mk_string m $ mk_operand_option op1 $ mk_operand_option op2 $ mk_operand_option op3 $ mk_word (a+si) 64
(* MakeadefinitioninHOLwithname"name"andasbody"value". ValuecanbeanyHOLterm,e.g.,: HOLogic.mk_number@{typnat}42 NotethatHOLtermscanbeproducedusingantiquotations,e.g., @{term"42::nat"} doesthesameastheabovecode.
*) fun mk_definition name value lthy = let val binding = Binding.name name val (_, lthy) = Local_Theory.define ((binding, NoSyn), ((Thm.def_binding binding, []), value)) lthy val _ = tracing ("Added definition: " ^ (Local_Theory.full_name lthy binding)) in
lthy end
fun main localename assembly lthy = let (* Build a locale name *) val _ = not (Long_Name.is_qualified localename) orelse raise Fail ("Given localename looks like qualified Isabelle ID: " ^ localename) val _ = localename <> "" orelse raise Fail ("Given localename is illegal")
(* The locale fixes a variable called "fetch" of type "64 word \<Longrightarrow> I" *) val fixes_fetch = Element.Fixes [( Binding.name "fetch" , SOME (@{typ "64 word => I"}), NoSyn)]
(* the locale contains a list of assumptions, one for each instruction. They are given the [simp] attribute. *) fun mk_assume thm_name term = ((Binding.name thm_name, @{attributes [simp]}), [term]); val mk_fetch = Free ("fetch", @{typ "64 word => I"}) fun mk_fetch_equality_assume si str = letval instr = parse_instr si str val (Instr (a,_,_,_,_,_)) = instr val asm_name = "fetch_" ^ LargeInt.toString a val eq_term = HOLogic.mk_eq (mk_fetch $ mk_word a 64, mk_instr instr lthy) in
mk_assume asm_name (HOLogic.Trueprop $ eq_term, []) end
val _ =
Outer_Syntax.local_theory
\<^command_keyword>\<open>x86_64_parser\<close> "Generate a locale from a list of assembly instructions."
(Parse.embedded -- Parse.embedded >> (fn (localename, assembly) => main localename assembly))
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.