Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- try:
- from tkinter import *
- except:
- print("No tkinter? This must not be Python 3!")
- raise SystemExit
- import random,re,array,os,sys
- from tkinter.filedialog import askopenfilename, asksaveasfilename
- ###############################################################
- #
- # Edlinas
- #
- ###############################################################
- #
- # This program is an x86 simulator which is intended for
- # instructional use. It is an updated version of a program
- # originally written in QBasic to support the book
- #
- # Linux Assembly Language Programming
- #
- # In addition to simulating an x86 processor, it also
- # functions as an assembler and an editor. Much of the
- # code for the program is based on the pseudo-C code in
- # Rakesh Agarwal's, "x86 Architecture and Programming."
- # In fact it should be possible to use that book as
- # documentation for this program, and vice versa.
- #
- # Much of the Tkinter code was adapted from examples
- # in John Grayson's book "Python and Tkinter Programming".
- #
- # The VerticalScrolledFrame class was taken from
- #
- # tkinter.unpy.net/wiki
- #
- # Thanks to John Stoddart for bringing in tkinter.filedialog.
- #
- # Bug and other error reports are welcome and may
- # be sent to Bob Neveln at:
- #
- # neveln@cs.widener.edu
- #
- ###############################################################
- #
- # ParseInit:
- #
- ###############################################################
- #
- #
- binary_mnemonics = ["ADD","OR","ADC","SBB","AND","SUB","XOR","CMP","MOV","ROL","ROR","RCL",
- "RCR","SHL","SHR","LDS","SAR","SAL","XCHG","TEST","IN","OUT","LES","LEA"]
- unary_mnemonics = ["JO","JNO","JB","JAE","JE","JNE","JBE","JA","JS","JNS","JP","JNP","JL",
- "JGE","JLE","JG","INC","DEC","JNAE","JNB","JZ","JNZ","JNA","JNBE","JO","JO","JO","JO",
- "JNGE","JNL","JNG","JNLE","NOT","NEG","JC","JNC","PUSH","POP","CALL","RET","RETF","RETN","INT","MUL","DIV","IDIV","LOOP","LOOPZ","LOOPNZ","LOOPE","LOOPNE","JCXZ","JECXZ","JMP","JMPF","CALLF","IMUL"]
- zrary_mnemonics = ["AAA","AAD","AAM","AAS","DAA","DAS","NOP","HLT","CLC","STC","CMC","CLD","CLI","STD","STI","INTO","IRET","IRETD","LAHF","POPF","POPFD","POPA","POPAD","PUSHF","PUSHFD","PUSHA","PUSHAD","SAHF","WAIT","CBW","CWD","XLATB","INSB","INSW","INSD","OUTSB","OUTSW","OUTSD","CMPSB","CMPSW","CMPSD","MOVSB","MOVSD","MOVSW","SCASB","SCASW","SCASD","STOSB","STOSW","STOSD","LODSB","LODSW","LODSD"]
- identifp = re.compile("([A-Za-z][\w_]*)")
- Arity = {}
- Archlev = {}
- for x in binary_mnemonics:
- Arity[x] = 2
- Archlev[x] = 0
- for x in unary_mnemonics:
- Arity[x] = 1
- Archlev[x] = 0
- for x in zrary_mnemonics:
- Arity[x] = 0
- Archlev[x] = 0
- Arity["RET"]= [0,1]
- Arity["RETF"] = [0,1]
- Arity["JMPF"] = [1,2]
- Arity["CALLF"] = [1,2]
- Arity["IMUL"] = [1,2,3]
- list_286 = ["LGDT","LIDT","LLDT","LTR","STR","SLDT","SGDT","SIDT","LMSW","SMSW","VERR","VERW","LEAVE","ARPL","LAR","LSL","BOUND","ENTER"]
- for x in list_286:
- Archlev[x] = 2
- Arity[x] = 1
- Arity["ARPL"] = 2
- Arity["LAR"] = 2
- Arity["LSL"] = 2
- Arity["BOUND"] = 2
- Arity["ENTER"] = 2
- Arity["LEAVE"] = 0
- list_386 =["BSF","BSR","BT","BTS","BTR","BTC","MOVZX","MOVSX","CWDE","CDQ","SETO","SETNO","SETB","SETAE","SETE","SETNE","SETBE","SETA","SETS","SETNS","SETP","SETNP","SETL","SETGE","SETLE","SETG","SHLD","SHRD","SETNAE","SETNB","SETZ","SETNZ","SETNA","SETNBE","LFS","LGS","LSS","CLTS","SETNGE","SETNL","SETNG","SETNLE"]
- for x in list_386:
- Archlev[x] = 3
- if x.startswith("S"):
- Arity[x] = 1
- else:
- Arity[x] = 2
- Arity["SHLD"] = 3
- Arity["SHRD"] = 3
- Arity["LFS"] = 2
- Arity["LGS"] = 2
- Arity["LSS"] = 2
- Arity["CLTS"] = 0
- Arity["CWDE"] = 0
- Arity["CDQ"] = 0
- list_486=["XADD","CMPXCHG","INVLPG","WBINVD","BSWAP","INVLPG","INVD"]
- for x in list_486:
- Archlev[x] = 4
- Arity["XADD"] = 2
- Arity["CMPXCHG"] = 2
- Arity["INVLPG"] = [0,1]
- Arity["WBINVD"] = 0
- Arity["BSWAP"] = 1
- list_586=["CMPXCHG8B","CPUID","RDTSC","RDMSR","WRMSR"]
- for x in list_586:
- Archlev[x] = 5
- Arity[x] = 0
- Arity["CMPXCHG8B"]=1
- mnemonic_list = ['place_holder'] + binary_mnemonics + unary_mnemonics + zrary_mnemonics + \
- list_286 + list_386 + list_486 + list_586
- index_insb = mnemonic_list.index("INSB")
- index_jo = mnemonic_list.index("JO")
- index_bt = mnemonic_list.index("BT")
- index_seto=mnemonic_list.index("SETO")
- index_rol=mnemonic_list.index("ROL")
- #Bits#(x,hi,lo) is the numerical value of x in binary reading digits [lo:hi+1]
- use_size = 32
- program_env = {}
- def build_line(source_line, line_num = ":"):
- lp = LineParse(source_line)
- if line_num == ":":
- error_string = "Error: "
- else:
- error_string = "Error line " + str(line_num) + ": "
- if type(lp) is str:
- message = error_string + lp + " "
- # print_feedback(message)
- return message
- (index, label, prefix,mnemonic, code, comment) = lp
- if label == '':
- rebuilt_source = prog.tabwidth * " " + source_line.lstrip() + "\n"
- elif len(label) < prog.tabwidth:
- rebuilt_source = (label + ":" + (prog.tabwidth * " "))[:prog.tabwidth] \
- + mnemonic + " " + code + comment + "\n"
- else: # Give up. Let the user deal with it.
- rebuilt_source = source_line
- if index < 0:
- message = error_string + "not ready for directives. "
- print_feedback(message)
- return message
- if index == 0:
- line = Line(rebuilt_source, '')
- line.label = label
- line.mnemonic = mnemonic
- else:
- ia = InstAssemble(code,index,prefix)
- if type(ia) is str:
- message = error_string + ia + " "
- # print_feedback(message)
- return message
- #
- # Here is the line to uncomment for debugging execution vs assembly errors:
- #
- print_feedback(ia)
- # print_feedback(" ", True) # Blanks entry box
- (op, displabel, dispcode, hx) = ia
- line = Line(rebuilt_source, hx)
- line.label = label
- line.mnemonic = mnemonic
- line.displabel = displabel
- line.dispcode = dispcode
- line.dispwidth = 1 << ((dispcode& 7) >> 1)
- return line
- def LineParse(code):
- """ Return [index, label, prefix, mnemonic, code, comment] or an error-message"""
- index = 0
- label = ''
- prefix = ''
- mnemonic= ''
- code = code.lstrip()
- semicolon_spot = code.find(';')
- if semicolon_spot != -1:
- comment = code[semicolon_spot:]
- code = code[:semicolon_spot]
- else:
- comment = ''
- while code and not mnemonic:
- if code[0] == '.':
- return 'Not ready for directives'
- identifm = identifp.match(code)
- if identifm:
- identif = identifm.group(1)
- code = code[identifm.end(1):].lstrip()
- upper_case = identif.upper()
- if upper_case in mnemonic_list:
- index = mnemonic_list.index(upper_case)
- if prefix :
- if prefix != "LOCK" and (index < index_insb or index > index_insb + 20):
- return "Can't repeat " + upper_case
- else:
- mnemonic = prefix + ' ' + identif
- elif code.startswith(':'):
- return identif + ' is a reserved word'
- else:
- mnemonic = identif
- elif upper_case in ['LOCK','REP','REPE','REPNE','REPZ','REPNZ']:
- if prefix:
- return 'Only one prefix allowed'
- elif upper_case == 'REPZ':
- prefix = 'REPE'
- elif upper_case == 'REPNZ':
- prefix = 'REPNE'
- else:
- prefix = upper_case
- else:
- if prefix:
- return 'Mis-spelling?'
- elif code.startswith(':'):
- code = code[1:].lstrip()
- else:
- code = code.lstrip()
- label = identif
- else:
- return 'Not a valid identifier'
- return [index, label, prefix, mnemonic, code, comment]
- def InstAssemble(code,index,prefix):
- displabel = ''
- dispcode = 0
- immc = ''
- size8_bit = 0
- if prefix == '':
- rlpf = ''
- elif prefix == "REP":
- rlpf = 'F3'
- elif prefix == "REPE":
- rlpf = 'F3'
- elif prefix == "REPNE":
- rlpf = 'F2'
- elif prefix == "LOCK":
- rlpf = 'F0'
- else:
- raise ValueError("Bad prefix: "+ prefix)
- if code:
- arglist = [x.strip() for x in code.split(',')]
- else:
- arglist = []
- n_args = len(arglist)
- mnemonic = mnemonic_list[index]
- if type(Arity[mnemonic]) is int:
- arity = Arity[mnemonic]
- if arity != n_args:
- if arity == 1:
- return mnemonic + ' takes 1 operand'
- else:
- return mnemonic + ' takes ' + str(arity) + ' operands'
- elif n_args in Arity[mnemonic]:
- arity = n_args
- else:
- return mnemonic + ': number of operands is in '+ str(Arity[mnemonic])
- # Stub values only:
- opc = ''
- op_code = -1
- mpf = ''
- ospf = ''
- if arity == 3:
- op3 = arglist[2]
- if op3 == '':
- return 'Third argument missing'
- op3_parse = OperandParse(op3)
- if type(op3_parse) is str:
- return op3_parse
- [op3_type, op3_tail, reg3_num, size3] = op3_parse
- if op3_type == 'imm':
- op3_imp = Immparse(op3)
- if type(op3_imp) is str:
- return op3_imp
- else:
- [label, oneb3, value3] = op3_imp
- if arity >= 2:
- op2 = arglist[1]
- if op2 == '':
- return 'Second argument missing'
- if mnemonic == "IN" and op2.startswith('[') and op2.endswith(']'):
- op2 = op2[1:-1].strip()
- elif mnemonic == "LEA" and op2.find('[')==-1:
- op2 = "[" + op2 + "]"
- op2_parse = OperandParse(op2)
- if type(op2_parse) is str:
- return op_parse2
- [op2_type,op2_tail,reg2_num,size2] = op2_parse
- if op2_type == 'imm':
- op2_imp = Immparse(op2)
- if type(op2_imp) is str:
- return op2_imp
- else:
- [label2, oneb2, value2] = op2_imp
- elif op2_type == 'reg':
- if size2 == 1:
- size2_bit = 1
- else:
- size2_bit = 0
- if arity >= 1:
- op1 = arglist[0]
- if op1 == '':
- return 'First argument missing'
- if mnemonic == "OUT" and op1.startswith('[') and op1.endswith(']'):
- op1 = op1[1:-1].strip()
- op1_parse = OperandParse(op1)
- if type(op1_parse) is str:
- return op_parse1
- [op1_type,op1_tail,reg1_num,size1] = op1_parse
- if op1_type == 'imm':
- op1_imp = Immparse(op1)
- if type(op1_imp) is str:
- return op1_imp
- else:
- [label1, oneb1, value1] = op1_imp
- displabel = label1
- elif size1 == 1:
- size8_bit = 1
- elif op1_type == 'reg':
- size8_bit = 0
- # return [op1_parse, op2_parse]
- if arity == 3:
- if size1 > 4 or size2 > 4 or size3 > 4:
- return 'General registers only'
- if mnemonic == "IMUL":
- if op3_type != "imm":
- return 'Third operand must be immediate'
- if op1_type != "reg":
- return 'First operand must be a register'
- if op2_type == "imm":
- return 'Second operand must be memory or a register'
- if size2 > 0 and size2 != size1:
- return 'Operand size mismatch'
- if size1 != (use_size >> 3):
- ospf = "66"
- if oneb3 == 1:
- op_code = 0x6b
- immc = ImmEncode(value3,-1)
- else:
- op_code = 0x69
- immc = ImmEncode(value3,-4)
- rmenc = RegMemEncode(reg1_num,size1,op2_type,op2_tail,reg2_num)
- if type(rmenc) is str:
- return rmenc
- [mpf, mx, displabel, dispcode] = rmenc
- if mnemonic in ["SHRD","SHLD"]:
- if mnemonic == "SHRD":
- op_code = 0xac
- else:
- op_code = 0xa4
- if op2_type != "reg":
- return 'Second operand must be a register'
- if op1_type == "imm":
- return 'First operand must be memory or a register'
- if size2 == 1:
- return 'One byte operand not allowed'
- if size1 > 0 and size1 != size2:
- return 'Operand size mismatch'
- if op3_type == "imm" and oneb3:
- immc = ImmEncode(value3,-1)
- elif op3_type == "imm" :
- return 'Third operand must be one byte'
- elif op3_type == "reg" and reg3_num == 1 and size3 ==1:
- op_code = op_code + 1
- else:
- return 'Third operand is CL or an immediate byte'
- opc = "0F"
- rmenc = RegMemEncode(reg2_num,size2,op1_type,op1_tail,reg1_num)
- if type(rmenc) is str:
- return rmenc
- [mpf, mx, displabel, dispcode] = rmenc
- elif arity == 2 and op1_type == 'imm':
- if mnemonic == "OUT":
- if op2_type != "reg" or reg2_num != 0:
- return 'Second argument must be AL, AX, or EAX'
- if 0 <= value1 < 256:
- op_code = 0xe7 - size2_bit
- immc = ImmEncode(value1,1)
- reg1_num = -1
- else:
- return 'Immediate port must be one byte'
- if size2 > 1 and size2 != (use_size>>3):
- ospf = "66"
- elif mnemonic == "ENTER":
- if op2_type != "imm":
- return 'Second argument must be immediate'
- elif oneb1:
- op_code = 0xc8
- immc = ImmEncode(value1, 1) + ImmEncode(value2,2)
- reg1_num = -1
- else:
- return 'Frame size is one byte'
- elif mnemonic == "JMPF":
- if op2_type != "imm":
- return 'Second argument must be immediate'
- else:
- op_code = 0xea
- immc = ImmEncode(value1, use_size>>3) + ImmEncode(value2,2)
- reg1_num = -1
- elif mnemonic == "CALLF":
- if op2_type != "imm":
- return 'Second argument must be immediate'
- else:
- op_code = 0x9a
- immc = ImmEncode(value1, use_size>>3) + ImmEncode(value2,2)
- reg1_num = -1
- else:
- return 'First operand cannot be immediate'
- mx = ''
- elif arity == 2 and op1_type == 'reg' and size1 > 4:
- if mnemonic == "MOV":
- if op2_type == "imm":
- return "Can't use an immediate"
- if size2 == 1:
- return op1_tail + " can't be one byte"
- if size2 > 4:
- return 'Second operand must be a general register'
- if size1 == 5: # Load Segment Register
- op_code = 0x8e
- elif size2 != 4 or op2_type != "reg" :
- return 'Need a 32 bit operand'
- elif size1 == 6: # Load Debug Register
- opc = "0F"
- op_code = 0x23
- elif size1 == 7: # Load Test Register
- opc = "0F"
- op_code = 0x26
- elif size1 == 8: # Load Control Register
- opc = "0F"
- op_code = 0x22
- elif size1 == 5:
- return 'Works only with MOV, PUSH or POP'
- else:
- return 'Try MOV'
- rmenc = RegMemEncode(reg1_num,size1,op2_type,op2_tail,reg2_num)
- if type(rmenc) is str:
- return rmenc
- [mpf, mx, displabel, dispcode] = rmenc
- elif arity == 2 and op2_type == 'reg' and size2 > 4:
- if mnemonic == "MOV":
- if size1 == 1:
- return op1_tail + " can't be one byte"
- if size1 > 4:
- return 'First operand must be a general register'
- if size2 == 5: # Store Segment Register
- op_code = 0x8c
- elif size1 != 4 or op1_type != "reg" :
- return 'Need a 32 bit operand'
- elif size2 == 6: # Store Debug Register
- opc = "0F"
- op_code = 0x21
- elif size2 == 7: # Store Test Register
- opc = "0F"
- op_code = 0x24
- elif size2 == 8: # Store Control Register
- opc = "0F"
- op_code = 0x20
- elif size2 == 5:
- return 'Works only with MOV, PUSH or POP'
- else:
- return 'Try MOV'
- rmenc = RegMemEncode(reg2_num,size2,op1_type,op1_tail,reg1_num)
- if type(rmenc) is str:
- return rmenc
- [mpf, mx, displabel, dispcode] = rmenc
- elif arity == 2 and op1_type == 'mem' and op2_type == 'mem':
- return 'Two memory operands not allowed'
- elif arity == 2 and op2_type == 'imm':
- # print "size1 = ", size1
- if mnemonic == "IN" and value2 < 256:
- pass
- elif size1 == 1 and oneb2 == 0:
- return "Immediate operand won't fit"
- if size1 == 1:
- size8_bit = 1
- else:
- size8_bit = 0
- # size1 = use_size >> 3
- # print "size1 = ", size1
- immc = ImmEncode(value2, -size1)
- if size1 != 1 and size1 != (use_size >> 3):
- ospf = "66"
- # print "size1 = ", size1
- # print "ospf =", ospf
- if mnemonic == "MOV":
- if op1_type == "reg":
- op_code = 0xb8 + reg1_num - (size8_bit<<3)
- reg2_num = -1
- else:
- op_code = 0xc7 - size8_bit
- reg2_num = 0
- elif mnemonic in ["ADD","OR","ADC","SBB","AND","SUB","XOR","CMP"]:
- oper_code = index - 1
- assert oper_code in range(8)
- if op1_type == "reg" and reg1_num == 0:
- op_code = (oper_code << 3) + 5 - size8_bit
- reg2_num = -1
- else:
- op_code = 0x81 - size8_bit
- reg2_num = oper_code
- elif mnemonic in ["ROL","ROR","RCL","RCR","SHL","SHR","SAR","SAL"]:
- if mnemonic == "SAL":
- reg2_num = 7
- else:
- reg2_num = index - index_rol
- if value2 == 1:
- op_code = 0xd1 - size8_bit
- immc = '' # Override default
- elif oneb2:
- op_code = 0xc1 - size8_bit
- immc = ImmEncode(value2, -1)
- else:
- return 'Shift count must be just one byte'
- elif mnemonic == "TEST":
- if op1_type == "reg" and reg1_num == 0:
- op_code = 0xa9 - size8_bit
- reg2_num = -1
- else:
- op_code = 0xf7 - size8_bit
- reg2_num = 0
- elif mnemonic in ["BT","BTS","BTR","BTC"]:
- if oneb2 and size1 != 1:
- opc = "0F"
- op_code = 0xba
- reg2_num = index - index_bt + 4
- immc = ImmEncode(value2, 1)
- elif size1 == 1:
- return 'Register cannot be one byte'
- else:
- return 'Immediate argument must be one byte'
- elif mnemonic == "IN":
- if op1_type != "reg" or reg1_num != 0:
- return 'First argument must be AL, AX, or EAX'
- elif 0 <= value2 < 256:
- immc = ImmEncode(value2, 1)
- else:
- return 'Immediate port must be one byte (Use DX)'
- op_code = 0xe5 - size8_bit
- reg2_num = -1
- elif mnemonic == "OUT":
- return 'Second argument must be AL, AX, or EAX'
- elif mnemonic == "IMUL":
- if op1_type != "reg":
- return 'First operand must be a register'
- elif size1 == 1:
- return 'One byte register not allowed'
- elif oneb2 == 1 :
- op_code = 0x6b
- immc = ImmEncode(value2, -1)
- else:
- op_cde = 0x69
- immc = ImmEncode(value2, -4)
- reg2_num = reg1_num
- op2_tail = op1_tail
- op2_type = op1_type
- else:
- return 'Second argument cannot be immediate'
- rmenc = RegMemEncode(reg2_num,size1,op1_type,op1_tail,reg1_num)
- if type(rmenc) is str:
- return rmenc
- [mpf, mx, displabel, dispcode] = rmenc
- elif arity == 2 and mnemonic in ["BSF","BSR","IMUL","LAR","LSL","MOVSX","MOVZX"]:
- if op1_type != "reg":
- return 'First operand must be a register'
- opc = "0F"
- if mnemonic == "LAR":
- op_code = 2
- elif mnemonic == "LSL":
- op_code = 3
- elif mnemonic == "BSF":
- op_code = 0xbc
- elif mnemonic == "BSR":
- op_code = 0xbd
- elif mnemonic == "IMUL":
- op_code = 0xaf
- elif mnemonic == "MOVSX":
- if size2 >= size1:
- return 'Second argment must be smaller than the first'
- elif size2 == -1:
- size2_bit = 0
- else:
- size2_bit = 1
- op_code = 0xbf - size2_bit
- elif mnemonic == "MOVZX":
- if size2 >= size1:
- return 'Second argment must be smaller than the first'
- elif size2 == -1:
- size2_bit = 0
- else:
- size2_bit = 1
- op_code = 0xb7 - size2_bit
- if size1 == 1:
- return 'First argument cannot be one byte'
- if size2 > -1 and size2 != size1 and mnemonic not in ["MOVZX","MOVSX"]:
- return 'Argument size mismatch'
- if size1 != (use_size>>3):
- ospf = "66"
- rmenc = RegMemEncode(reg1_num,size2,op2_type,op2_tail,reg2_num)
- if type(rmenc) is str:
- return rmenc
- [mpf, mx, displabel, dispcode] = rmenc
- elif arity == 2 and op2_type == 'reg':
- if mnemonic == "MOV":
- op_code = 0x89 - size2_bit
- elif mnemonic in ["ADD","OR","ADC","SBB","AND","SUB","XOR","CMP"]:
- oper_code = index - 1
- op_code = (oper_code << 3) + 1 - size2_bit
- elif mnemonic in ["ROL","ROR","RCL","RCR","SHL","SHR","SAR","SAL"]:
- if reg2_num != 1 or size2 != 1:
- return 'Shift count must be CL or an immediate'
- else:
- op_code = 0xd3 - size8_bit
- reg2_num = index- index_rol
- size2 = size1
- size1 = -1
- if mnemonic == "SAL": reg2_num = 4
- elif mnemonic in ["XCH","XCHG"]:
- if op1_type == "reg" and reg1_num == 0 and size8_bit==0 :
- op_code = 0x90 + reg2_num
- reg2_num = -1
- else:
- op_code = 0x87 - size8_bit
- elif mnemonic in ["BT","BTS","BTR","BTC"]:
- opc = "0F"
- op_code = 0xa3 + ((index - index_bt) << 3)
- elif mnemonic == "TEST":
- op_code = 0x85 - size2_bit
- elif mnemonic == "XADD":
- opc = "0F"
- op_code = 0xc1 - size2_bit
- elif mnemonic == "CMPXCHG":
- opc = "0F"
- op_code = 0xa7 - size2_bit
- elif mnemonic == "IN":
- if reg2_num != 2 or size2 != 2: # DX
- return 'Port must be DX or an immediate byte'
- elif op1_type != "reg" or reg1_num != 0:
- return 'First argument is AL, AX, or EAX'
- else:
- op_code = 0xed - size8_bit
- reg2_num = -1
- size2 = size1
- size1 = -1
- elif mnemonic == "OUT":
- if reg2_num != 0: # EAX
- return 'Second argument is AL, AX, or EAX'
- elif op1_type != "reg" or reg1_num != 2 or size1 != 2: # DX
- return 'Port must be DX or an immediate byte'
- else:
- op_code = 0xef - size2_bit
- reg2_num = -1
- size1 = -1
- elif mnemonic == "ARPL":
- if size2 != 2:
- return '16 bit arguments needed'
- else:
- op_code = 0x63
- size2 = -1
- else:
- return 'Register not allowed as second argument'
- if size1 > 0 and size2 > 0 and size1 != size2:
- return 'Operand size mismatch'
- if size2 > 1 and size2 != (use_size >> 3):
- ospf = "66"
- rmenc = RegMemEncode(reg2_num,size1,op1_type,op1_tail,reg1_num)
- if type(rmenc) is str:
- return rmenc
- [mpf, mx, displabel, dispcode] = rmenc
- elif arity == 2: #op2_type == 'mem'
- if mnemonic == "MOV":
- op_code = 0x8b - size8_bit
- elif mnemonic in ["ADD","OR","ADC","SBB","AND","SUB","XOR","CMP"]:
- oper_code = index - 1
- op_code = (oper_code << 3) + 3 - size8_bit
- elif mnemonic in ["ROL","ROR","RCL","RCR","SHL","SHR","SAR","SAL"]:
- return 'Shift count must be CL or an immediate'
- elif mnemonic in ["XCH","XCHG"]:
- if op1_type != "reg":
- return 'First operand must be a register'
- op_code = 0x87 - size8_bit
- elif mnemonic == "LEA":
- if size8_bit == 1:
- return "Addresses can't be 8 bits"
- op_code = 0x8d
- elif mnemonic == "TEST":
- op_code = 0xf6
- elif mnemonic == "BOUND":
- op_code = 0x62
- elif mnemonic == "LDS":
- op_code = 0xc5
- elif mnemonic == "LES":
- op_code = 0xc4
- elif mnemonic == "LFS":
- op_code = 0xb4
- elif mnemonic == "LGS":
- op_code = 0xb5
- elif mnemonic == "LSS":
- op_code = 0xb2
- elif mnemonic == "IN":
- return 'Port must be DX or an immediate byte'
- elif mnemonic == "OUT":
- return 'Second operand must be AL,AX, or EAX'
- else:
- return "Second operand can't be memory"
- if size2 > 0 and size1 != size2:
- return 'Operand size mismatch'
- if size1 > 1 and size1 != (use_size >> 3):
- ospf = "66"
- rmenc = RegMemEncode(reg1_num,size2,op2_type,op2_tail,reg2_num)
- if type(rmenc) is str:
- return rmenc
- [mpf, mx, displabel, dispcode] = rmenc
- elif arity == 1 and op1_type == "reg" and size1 == 5:
- if mnemonic == "PUSH":
- if op1_tail == "DS":
- op_code = 0x1e
- elif op1_tail == "ES":
- op_code = 0x6
- elif op1_tail == "CS":
- op_code = 0xe
- elif op1_tail == "SS":
- op_code = 0x16
- elif op1_tail == "FS":
- opc = "0F"
- op_code = 0xa0
- elif op1_tail == "GS":
- opc = "0F"
- op_code = 0xa8
- elif mnemonic == "POP":
- if op1_tail == "DS":
- op_code = 0x1f
- elif op1_tail == "ES":
- op_code = 0x7
- elif op1_tail == "CS":
- return "Can't pop CS"
- elif op1_tail == "SS":
- op_code = 0x17
- elif op1_tail == "FS":
- opc = "0F"
- op_code = 0xa1
- elif op1_tail == "GS":
- opc = "0F"
- op_code = 0xa9
- elif arity == 1 and op1_type == 'reg' and size1 > 1 and\
- mnemonic in ["INC","DEC","POP","PUSH","BSWAP"]:
- if mnemonic == "INC":
- op_code = 0x40 + reg1_num
- elif mnemonic == "DEC":
- op_code = 0x48 + reg1_num
- elif mnemonic == "PUSH":
- op_code = 0x50 + reg1_num
- elif mnemonic == "POP":
- op_code = 0x58 + reg1_num
- elif mnemonic == "BSWAP":
- opc = "0F"
- op_code = 0xc8 + reg1_num
- if size1 < 4:
- return '32 bits only'
- if size1 != (use_size >> 3):
- ospf = "66"
- mx = ''
- elif arity == 1 and mnemonic.startswith("SET"):
- if op1_type == "imm":
- return 'First operand must be register or memory'
- if size1 > 1:
- return 'Set just one byte'
- opc = "0F"
- op_code = 0x90 + index - index_seto
- if op_code > 0xa0:
- op_code = op_code - 0x10
- reg_bits = 0
- rmenc = RegMemEncode(reg_bits,size1,op1_type,op1_tail,reg1_num)
- if type(rmenc) is str:
- return rmenc
- [mpf, mx, displabel, dispcode] = rmenc
- elif arity == 1 and op1_type == 'imm':
- if label1 == '' :
- if mnemonic == "PUSH":
- if oneb1:
- op_code = 0x6a
- immc = ImmEncode(value1,-1)
- elif use_size == 16:
- op_code = 0x68
- immc = ImmEncode(value1,2)
- else:
- op_code = 0x68
- immc = ImmEncode(value1,4)
- elif mnemonic in ["RET","RETN"]:
- op_code = 0xc2
- immc = ImmEncode(value1,2)
- elif mnemonic == "RETF":
- op_code = 0xca
- immc = ImmEncode(value1,2)
- elif mnemonic == "INT":
- if value1 == 3:
- op_code = 0xcc
- immc = ''
- else:
- op_code = 0xcd
- immc = ImmEncode(value1,1)
- elif mnemonic in ["MUL","DIV","IDIV","POP","INC","DEC","NOT","NEG"]:
- return 'Argument must be register or memory'
- else:
- return 'Label needed'
- else:
- if use_size == 32:
- immc = ImmEncode(value1,-4)
- dispcode = 0xd
- elif use_size == 16:
- immc = ImmEncode(value1,-2)
- dispcode = 0xb
- displabel = label1
- if mnemonic == "PUSH":
- op_code = 0x68
- if use_size == 16:
- dispcode = 2
- elif use_size == 32:
- dispcode = 4
- elif mnemonic in ["JO", "JNO", "JB", "JAE", "JE", "JNE", "JBE", "JA", "JS", "JNS", "JL", "JGE", "JLE", "JG"]:
- op_code = 0x80 + index - index_jo
- opc = "0F"
- elif mnemonic in ["JNAE", "JNB", "JZ", "JNZ", "JNA", "JNBE", "JNGE", "JNL", "JNG", "JNLE"]:
- op_code = 0x80 + index - index_jo - 16
- opc = "0F"
- elif mnemonic in ["JC","JNC"]:
- op_code = 0x80 + index - index_jo - 32
- opc = "0F"
- elif mnemonic == "JMP":
- op_code = 0xe9
- elif mnemonic == "CALL":
- op_code = 0xe8
- elif mnemonic == "JMPF":
- op_code = 0xea
- elif mnemonic == "CALLF":
- op_code = 0x9a
- elif mnemonic in ["RET", "RETN", "RETF", "INT"]:
- return 'Argument may be an immediate but not a label'
- elif mnemonic in ["LOOPNZ", "LOOPNE"]:
- op_code = 0xe0
- immc = '00'
- dispcode = 9
- elif mnemonic in ["LOOPZ", "LOOPE"]:
- op_code = 0xe1
- immc = '00'
- dispcode = 9
- elif mnemonic == "LOOP":
- op_code = 0xe2
- immc = '00'
- dispcode = 9
- elif mnemonic == "JECXZ":
- op_code = 0xe3
- if use_size == 16:
- opc = "66"
- immc = '00'
- dispcode = 9
- elif mnemonic == "JCXZ":
- op_code = 0xe3
- if use_size == 32:
- opc = "66"
- immc = '00'
- dispcode = 9
- else:
- return 'Argument must be register or memory'
- mx = ''
- elif arity == 1:
- if size1 > 1 and size1 != (use_size >> 3):
- ospf = "66"
- if mnemonic == "INC":
- reg_bits = 0
- op_code = 0xff - size8_bit
- elif mnemonic == "DEC":
- reg_bits = 1
- op_code = 0xff - size8_bit
- elif mnemonic == "NOT":
- reg_bits = 2
- op_code = 0xf7 - size8_bit
- elif mnemonic == "NEG":
- reg_bits = 3
- op_code = 0xf7 - size8_bit
- elif mnemonic == "MUL":
- reg_bits = 4
- op_code = 0xf7 - size8_bit
- elif mnemonic == "IMUL":
- reg_bits = 5
- op_code = 0xf7 - size8_bit
- elif mnemonic == "DIV":
- reg_bits = 6
- op_code = 0xf7 - size8_bit
- elif mnemonic == "IDIV":
- reg_bits = 7
- op_code = 0xf7 - size8_bit
- elif mnemonic == "PUSH":
- reg_bits = 6
- op_code = 0xff
- elif mnemonic == "POP":
- reg_bits = 0
- op_code = 0x8f
- elif mnemonic == "JMP":
- reg_bits = 4
- op_code = 0xff
- elif mnemonic == "CALL":
- reg_bits = 2
- op_code = 0xff
- elif mnemonic == "JMPF":
- reg_bits = 5
- op_code = 0xff
- elif mnemonic == "CALLF":
- reg_bits = 3
- op_code = 0xff
- # The following op codes get prefixed by 0F
- elif mnemonic == "SLDT":
- reg_bits = 0
- op_code = 0
- elif mnemonic == "STR":
- reg_bits = 1
- op_code = 0
- elif mnemonic == "LLDT":
- reg_bits = 2
- op_code = 0
- elif mnemonic == "LTR":
- reg_bits = 3
- op_code = 0
- elif mnemonic == "VERR":
- reg_bits = 4
- op_code = 0
- elif mnemonic == "VERW":
- reg_bits = 5
- op_code = 0
- elif mnemonic == "SGDT":
- reg_bits = 0
- op_code = 1
- elif mnemonic == "SIDT":
- reg_bits = 1
- op_code = 1
- elif mnemonic == "LGDT":
- reg_bits = 2
- op_code = 1
- elif mnemonic == "LIDT":
- reg_bits = 3
- op_code = 1
- elif mnemonic == "SMSW":
- reg_bits = 4
- op_code = 1
- elif mnemonic == "LMSW":
- reg_bits = 6
- op_code = 1
- elif mnemonic == "INVLPG":
- reg_bits = 7
- op_code = 1
- if op_code in [0,1]:
- opc = "0F"
- if size1 != 2:
- return 'Operand must be 2 bytes'
- else:
- ospf = ''
- if size1 == 1 and mnemonic in ["PUSH","POP"]:
- return "Can't push or pop single bytes"
- if op1_type == "reg" and mnemonic in ["SGDT", "SIDT","LIDT", "LGDT"]:
- return 'Takes memory operand only'
- if reg_bits > -1:
- rmenc = RegMemEncode(reg_bits,size1,op1_type,op1_tail,reg1_num)
- if type(rmenc) is str:
- return rmenc
- [mpf, mx, displabel, dispcode] = rmenc
- else:
- mx = ''
- elif arity == 0:
- if code:
- return "argument '" + code + "' given to " + mnemonic
- if prefix == "REP":
- if mnemonic[:3] in ["CMP","SCA"]:
- return prefix + mnemonic + ' invalid combination'
- elif prefix in ["REPE","REPNE"]:
- if mnemonic[:3] not in ["CMP","SCA"]:
- return prefix + mnemonic + ' invalid combination'
- if mnemonic == "AAA":
- op_code = 0x37
- elif mnemonic == "AAD":
- opc = "D5"
- op_code = 0xa
- elif mnemonic == "AAM":
- opc = "D4"
- op_code = 0xa
- elif mnemonic == "AAS":
- op_code = 0x3f
- elif mnemonic == "CBW":
- op_code = 0x98
- if use_size == 32:
- opc = "66"
- elif mnemonic == "CWDE":
- op_code = 0x98
- if use_size == 16:
- opc = "66"
- elif mnemonic == "CDQ":
- op_code = 0x99
- if use_size == 16:
- opc = "66"
- elif mnemonic == "CWD":
- op_code = 0x99
- if use_size == 32:
- opc = "66"
- elif mnemonic == "CLC":
- op_code = 0xf8
- elif mnemonic == "CLD":
- op_code = 0xfc
- elif mnemonic == "CLI":
- op_code = 0xfa
- elif mnemonic == "CLTS":
- opc = "0F"
- op_code = 0x6
- elif mnemonic == "CMC":
- op_code = 0xf5
- elif mnemonic == "CMPSB":
- op_code = 0xa6
- elif mnemonic == "CMPSW":
- op_code = 0xa7
- if use_size == 32:
- opc = "66"
- elif mnemonic == "CMPSD":
- op_code = 0xa7
- if use_size == 16:
- opc = "66"
- elif mnemonic == "CWD":
- op_code = 0x99
- if use_size == 32:
- opc = "66"
- elif mnemonic == "CWDE":
- op_code = 0x98
- if use_size == 16:
- opc = "66"
- elif mnemonic == "DAA":
- op_code = 0x27
- elif mnemonic == "DAS":
- op_code = 0x2f
- elif mnemonic == "HLT":
- op_code = 0xf4
- elif mnemonic == "INSB":
- op_code = 0x6c
- elif mnemonic == "INSW":
- op_code = 0x6d
- if use_size == 32:
- opc = "66"
- elif mnemonic == "INSD":
- op_code = 0x6d
- if use_size == 16:
- opc = "66"
- elif mnemonic == "INTO":
- op_code = 0xce
- elif mnemonic == "INVD":
- opc = "0F"
- op_code = 0x8
- elif mnemonic in ["IRET","IRETD"]:
- op_code = 0xcf
- elif mnemonic == "LAHF":
- op_code = 0x9f
- elif mnemonic == "LEAVE":
- op_code = 0x9
- elif mnemonic == "LOADALL286":
- opc = "0F"
- op_code = 0x5
- elif mnemonic == "LODSB":
- op_code = 0xac
- elif mnemonic == "LODSW":
- op_code = 0xad
- if use_size == 32:
- opc = "66"
- elif mnemonic == "LODSD":
- op_code = 0xad
- if use_size == 16:
- opc = "66"
- elif mnemonic == "MOVSB":
- op_code = 0xa4
- elif mnemonic == "MOVSW":
- op_code = 0xa5
- if use_size == 32:
- opc = "66"
- elif mnemonic == "MOVSD":
- op_code = 0xa5
- if use_size == 16:
- opc = "66"
- elif mnemonic == "NOP":
- op_code = 0x90
- elif mnemonic == "OUTSB":
- op_code = 0x6e
- elif mnemonic == "OUTSW":
- op_code = 0x6f
- if use_size == 32:
- opc = "66"
- elif mnemonic == "OUTSD":
- op_code = 0x6f
- if use_size == 16:
- opc = "66"
- elif mnemonic in ["POPA","POPD"]:
- op_code = 0x61
- elif mnemonic == "POPF":
- op_code = 0x9d
- if use_size == 32:
- oc = "66"
- elif mnemonic == "POPFD":
- op_code = 0x9d
- if use_size == 16:
- oc = "66"
- elif mnemonic in ["PUSHA","PUSHAD"]:
- op_code = 0x60
- elif mnemonic == "PUSHF":
- op_code = 0x9c
- if use_size == 32:
- oc = "66"
- elif mnemonic == "PUSHFD":
- op_code = 0x9c
- if use_size == 16:
- oc = "66"
- elif mnemonic in ["RET","RETN"]:
- op_code = 0xc3
- elif mnemonic == "RETF":
- op_code = 0xcb
- elif mnemonic == "SAHF":
- op_code = 0x9e
- elif mnemonic == "SCASB":
- op_code = 0xae
- elif mnemonic == "SCASW":
- op_code = 0xaf
- if use_size == 32:
- oc = "66"
- elif mnemonic == "SCASD":
- op_code = 0xaf
- if use_size == 16:
- oc = "66"
- elif mnemonic == "STC":
- op_code = 0xf9
- elif mnemonic == "STD":
- op_code = 0xfd
- elif mnemonic == "STI":
- op_code = 0xfb
- elif mnemonic == "STOSB":
- op_code = 0xaa
- elif mnemonic == "STOSW":
- op_code = 0xab
- if use_size == 32:
- oc = "66"
- elif mnemonic == "STOSD":
- op_code = 0xab
- if use_size == 16:
- oc = "66"
- elif mnemonic == "WAIT":
- op_code = 0x9b
- elif mnemonic == "WBINVD":
- opc = "0F"
- op_code = 0x9
- elif mnemonic == "XLATB":
- op_code = 0xd7
- mx = ''
- if op_code > -1:
- opc = opc + "%02X" % op_code
- else:
- opc = ''
- if displabel:
- dispcode = (len(immc)<< 3) + dispcode
- dispcode = dispcode | 8
- else:
- dispcode = 0
- packed_op = ''
- hx = rlpf + ospf + mpf + opc + mx + immc
- return (packed_op, displabel, dispcode, hx)
- register_list = ["EAX","ECX","EDX","EBX","ESP","EBP","ESI","EDI","AX","CX","DX","BX","SP","BP","SI","DI","AL","CL","DL","BL","AH","CH","DH","BH","ES","CS","SS","DS","FS","GS","LDT","TSS","DR0","DR1","DR2","DR3","DR4","DR5","DR6","DR7","TR0","TR1","TR2","TR3","TR4","TR5","TR6","TR7","CR0","CR1","CR2","CR3","CR4"]
- def OperandParse(op):
- op = op.strip()
- n_bytes = -1
- if op.upper() in register_list:
- reg_num = register_list.index(op.upper())
- else:
- reg_num = -1
- if reg_num > -1:
- optype = "reg"
- if reg_num < 8:
- n_bytes = 4
- elif reg_num < 16:
- n_bytes = 2
- elif reg_num < 24:
- n_bytes = 1
- else:
- n_bytes = ((reg_num - 24) >> 3) + 5 # Just a code, not really a size.
- reg_num = reg_num & 7
- if reg_num > 5 and n_bytes == 5: # LDT and TSS
- return op + ' not addressable'
- elif "[" in op:
- optype = "mem"
- if op.upper().startswith('BYTE'):
- n_bytes = 1
- op = op[4:].lstrip()
- elif op.upper().startswith('2BYTE'):
- n_bytes = 2
- op = op[5:].lstrip()
- elif op.upper().startswith('WORD'):
- n_bytes = 2
- op = op[4:].lstrip()
- elif op.upper().startswith('4BYTE'):
- n_bytes = 4
- op = op[5:].lstrip()
- elif op.upper().startswith('DWORD'):
- n_bytes = 4
- op = op[5:].lstrip()
- if op.upper().startswith('PTR'):
- op = op[4:].lstrip()
- if op.find(':') == 2:
- sreg = op[:2].upper()
- if sreg in register_list:
- sreg_num = register_list.index(sreg)
- if 24 <= sreg_num < 30:
- reg_num = sreg_num - 24
- op = op[3:].lstrip()
- else:
- return sreg + ' not a segment register'
- else:
- return sreg + ' not a segment register'
- else:
- optype = "imm"
- return [optype,op,reg_num,n_bytes]
- def RegMemEncode(reg_bits, reg_size, rm_type, rm, mem_bits):
- label = ''
- dispcode = 0
- if reg_bits == -1:
- pf = ''
- mx = ''
- elif rm_type == "reg":
- pf = ''
- mx = "%02X" % (0xc0 + (reg_bits<<3) + mem_bits)
- else:
- ma = MemAssemble(reg_bits, reg_size, rm_type, rm, mem_bits)
- if type(ma) is str:
- # print ma + ' is a string'
- # raise SystemExit
- return ma
- [pf, mx, label, dispcode, sreg] = ma
- # print "mem_bits = ",mem_bits
- # print "sreg = ",sreg
- pf = pf + SegPref(mem_bits, sreg)
- return [pf, mx, label, dispcode]
- def MemAssemble(reg_bits, reg_size, rm_type, rm, sgreg):
- left_end = rm.find("[")
- right_end = rm.rfind("]")
- rm = rm[left_end + 1:right_end]
- scale = 1
- ind_reg = -1
- base_reg1 = -1
- base_reg2 = -1
- additive_constant = 0
- lbl = ''
- start = 0
- paren_depth = 0
- term_in_midst = False
- sign_is_negative = False
- old_sign_is_negative = False
- while start < len(rm):
- # print "neg", sign_is_negative
- k = start
- c = ''
- while c not in ['+','-','*'] and k < len(rm):
- c = rm[k]
- k = k + 1
- if c == '(':
- paren_depth = paren_depth + 1
- elif c == ')':
- paren_depth = paren_depth - 1
- if paren_depth > 0:
- c = ''
- if paren_depth != 0:
- return 'Unbalanced parentheses'
- if k == len(rm):
- x = rm[start:k].strip()
- else:
- x = rm[start:k-1].strip()
- start = k
- if x.upper() in register_list:
- reg_num = register_list.index(x.upper())
- else:
- reg_num = -1
- if reg_num > 15:
- return 'Register must be 16 or 32 bit general register'
- if term_in_midst:
- if reg_num >= 0 and ind_reg >= 0:
- return "Registers can't be multiplied"
- elif reg_num >= 0:
- ind_reg = reg_num
- else:
- imp = Immparse(x)
- if type(imp) is str:
- return imp
- inlbl, one_byte, value = imp
- if inlbl:
- return 'Labels not allowed in scale factor'
- else:
- scale = scale * value
- if c != '*':
- if ind_reg < 0 and sign_is_negative:
- additive_constant = additive_constant - scale
- scale = 1
- elif ind_reg < 0:
- additive_constant = additive_constant + scale
- scale = 1
- elif scale not in [1,2,4,8]:
- return 'Scale must be 1,2,4, or 8'
- elif scale == 1:
- if base_reg1 < 0:
- base_reg1 = ind_reg
- ind_reg = -1
- elif base_reg2 < 0:
- base_reg2 = ind_reg
- ind_reg = -1
- else:
- return 'Maximum 2 registers'
- term_in_midst = False
- if c == '-':
- return "Can't subtract products"
- elif c == '*':
- if reg_num >= 0 and ind_reg >= 0:
- return 'Only 1 register can be scaled'
- elif reg_num >= 0:
- ind_reg = reg_num
- else:
- imp = Immparse(x)
- if type(imp) is str:
- return imp
- inlbl, one_byte, value = imp
- if inlbl:
- return 'Labels not allowed in scale factor'
- scale = scale * value
- term_in_midst = True
- else:
- if reg_num >= 0:
- if base_reg1 < 0:
- base_reg1 = reg_num
- elif base_reg2 < 0:
- base_reg2 = reg_num
- else:
- return 'Maximum 2 registers'
- if sign_is_negative:
- return "Can't subtract a register"
- else:
- imp = Immparse(x)
- if type(imp) is str:
- return imp
- inlbl, one_byte, value = imp
- # print("imp = ", imp)
- if inlbl == '' and sign_is_negative:
- additive_constant = additive_constant - value
- elif inlbl == '':
- additive_constant = additive_constant + value
- elif lbl == '':
- lbl = inlbl
- sign_is_negative = (c == '-')
- #
- # Check results
- #
- if ind_reg >= 0 and base_reg1 >= 0 and base_reg2 >= 0:
- return 'At most two registers allowed'
- if ind_reg >= 16 or base_reg1 >= 16 or base_reg2 >= 16:
- return 'No one byte addresses'
- if ind_reg >= 0 and (base_reg1 >= 8 or base_reg2 >= 8):
- return 'Scaling used only in 32 bit addresses'
- if (0 <= base_reg1 < 8 and base_reg2 >= 8) or (0 <= base_reg2 < 8 and base_reg1 >= 8):
- return 'Conflicting address sizes'
- if 0 <= base_reg2 < 8:
- if sgreg == 2 and base_reg2 in [4,5]: # SS and [ESP,EBP]
- base_reg1, base_reg2 = base_reg2, base_reg1
- elif sgreg == 3 and base_reg2 not in [4,5]: # DS and not [ESP,EBP]
- base_reg1, base_reg2 = base_reg2, base_reg1
- ind_reg, base_reg2 = base_reg2, ind_reg
- adlen = 32
- elif ind_reg >= 0:
- adlen = 32
- elif 0 <= base_reg1 < 8:
- adlen = 32
- elif 0 <= base_reg2:
- if base_reg2 in [11,13]: # [BX, BP]
- base_reg1, base_reg2 = base_reg2, base_reg1
- if base_reg1 not in [11,13]: # [BX, BP]
- return '16 bit base must be BX or BP'
- if base_reg2 not in [14,15]: # [SI, DI]
- return '16 bit index must be SI or DI'
- ind_reg, base_reg2 = base_reg2, ind_reg
- adlen = 16
- elif base_reg1 >= 8:
- if base_reg1 < 11 or base_reg1 == 12:
- return 'Need BX, BP, SI, or DI'
- if base_reg1 in [14,15]: #[SI,DI]
- ind_reg, base_reg1 = base_reg1, ind_reg
- adlen = 16
- elif base_reg1 >= 0:
- adlen = 32
- else:
- adlen = use_size
- if adlen != use_size:
- pf = "67"
- else:
- pf = ''
- if additive_constant < -(1<<31) or additive_constant >= 1<< 32:
- return '32 bits Maximum'
- if adlen == 32:
- if lbl != '' or base_reg1 < 0:
- n_dbytes = 4
- elif additive_constant < -128 or additive_constant >= 128:
- n_dbytes = 4
- elif additive_constant != 0 or base_reg1 == 5: # EBP
- n_dbytes = 1
- else:
- n_dbytes = 0
- if base_reg1 in [4,5]: # ESP or EBP
- sreg = 2 # SS
- else:
- sreg = 3 # DS
- if ind_reg == 4:
- return "Index register can't be ESP"
- memb = MemEncode32(reg_bits, scale, base_reg1, ind_reg, n_dbytes)
- elif adlen == 16:
- if lbl != '' or base_reg1 < 0:
- n_dbytes = 2
- elif additive_constant < -128 or additive_constant >= 128:
- n_dbytes = 2
- elif additive_constant != 0 or (base_reg1 == 13 and ind_reg < 0): # BP
- n_dbytes = 1
- else:
- n_dbytes = 0
- if base_reg1 == 13: # BP
- sreg = 2 # SS
- else:
- sreg = 3 # DS
- memb = MemEncode16(reg_bits, base_reg1, ind_reg, n_dbytes)
- assert n_dbytes in [0,1,2,4]
- if n_dbytes != 0:
- disp = ImmEncode(additive_constant,- n_dbytes)
- else:
- disp = ''
- if n_dbytes == 0:
- dispcode = 0
- elif n_dbytes == 1:
- dispcode = 0
- elif n_dbytes == 2:
- dispcode = 2
- elif n_dbytes == 4:
- dispcode = 4
- dispcode = dispcode + (n_dbytes<<4)
- mx = memb + disp
- return [pf, mx, lbl, dispcode, sreg]
- def SegPref(specified, encoded):
- if specified == -1 or specified == encoded:
- return ''
- if specified == 1: # CS
- return "2E"
- if specified == 3: # DS
- return "1E"
- if specified == 0: # ES
- return "26"
- if specified == 4: # FS
- return "64"
- if specified == 5: # GS
- return "65"
- if specified == 2: # SS
- return "36"
- raise ValueError("specified, encoded = " + str(specified) + str(encoded))
- def Immparse(op):
- if identifp.match(op):
- if op in program_env:
- value = program_env[op]
- if type(value) is str:
- return op + ' must be defined as an integer'
- if -128 <= value < 128:
- return ['',1,value]
- else:
- return ['',0,value]
- else:
- return [op,0,0]
- if op.startswith('(') and op.endswith(')'):
- return Immparse(op[1:-1])
- nump = Numparse(op)
- if type(nump) is int:
- if -128 <= nump < 256:
- # if -128 <= nump < 128:
- return ['',1,nump]
- else:
- return ['',0,nump]
- elif type(nump) is int:
- if -0x80000000 <= nump < 0x100000000:
- return ['',0,nump]
- else:
- return op + ' not a valid 4 byte number'
- if '+' not in op and '-' not in op and '*' not in op:
- return op + ' not a valid immediate expression'
- m = mainsplit(op,['+','-'])
- label = ''
- if len(m) > 2:
- eval_list = []
- for k in range(0,len(m),2):
- if m[k]:
- imp = Immparse(m[k])
- if type(imp) is str:
- return imp
- outlabel,single_byte,val = imp
- if label and outlabel:
- return 'Only one label allowed'
- if outlabel:
- label = outlabel
- eval_list.append(str(val))
- eval_list.append(m[k+1])
- else:
- eval_list.append(m[k+1])
- eval_list.pop()
- try:
- retval = eval(''.join(eval_list))
- except:
- return 'Bad expression'
- if -128 <= retval < 128:
- return [label,1,retval]
- else:
- return [label,0,retval]
- m = mainsplit(op,['*'])
- if len(m) > 1:
- retval = 1
- for k in range(0,len(m),2):
- if m[k] == '':
- return 'Bad multiplicative expression'
- imp = Immparse(m[k])
- if type(imp) is str:
- return imp
- outlabel,single_byte,val = imp
- if outlabel:
- return 'No multiplicative labels'
- retval = val * retval
- if -128 <= retval < 128:
- return ['',1,retval]
- else:
- return ['',0,retval]
- def Numparse(num_string):
- if num_string.startswith('-'):
- num_string= num_string[1:]
- sign = -1
- else:
- sign = 1
- if num_string.endswith('H') or num_string.endswith('h'):
- num_string= num_string[:-1]
- try:
- val = int(num_string,16)
- except:
- return 'Invalid integer'
- elif num_string.startswith('0x') or num_string.startswith('0X'):
- try:
- val = int(num_string,16)
- except:
- return 'Invalid integer'
- elif num_string.startswith('0'):
- try:
- val = int(num_string,8)
- except:
- return 'Invalid integer'
- elif num_string.isdigit():
- val = int(num_string)
- else:
- return 'Invalid integer'
- val = sign * val
- return val
- def mainsplit(expression,oplist):
- paren_depth = 0
- retlist = []
- last_i = -1
- for i,x in enumerate(expression + oplist[0]):
- if x == '(':
- paren_depth = paren_depth + 1
- elif x == ')':
- paren_depth = paren_depth - 1
- if paren_depth == 0 and x in oplist:
- y = expression[last_i + 1:i].strip()
- last_i = i
- retlist.append(y)
- retlist.append(x)
- return retlist
- def MemEncode32(reg_num, scale, base_reg, ind_reg, n_dbytes):
- # REG.NUM is /r. This may or may not code a register.
- # BASE.REG is the base register. -1 if there is none.
- # IND.REG is the index register. -1 if there is none.
- # N.DBYTES is the number of displacement bytes to follow.
- # print (reg_num, scale, base_reg, ind_reg, n_dbytes)
- sib = -1 # Default for no SIB byte.
- if n_dbytes == 4:
- disp_bits = 2
- elif n_dbytes == 1:
- disp_bits = 1
- elif n_dbytes == 0:
- disp_bits = 0
- if scale == 8:
- scale_bits = 3
- elif scale == 4:
- scale_bits = 2
- elif scale == 2:
- scale_bits = 1
- elif scale == 1:
- scale_bits = 0
- assert ind_reg != 4 # 4 = ESP
- assert base_reg != 5 or n_dbytes != 0 #5 = EBP
- assert base_reg != -1 or not(n_dbytes == 0 or n_dbytes == 1)
- # This case should be blocked in MemAssemble
- if ind_reg >= 0 and base_reg >= 0:
- rm = (disp_bits << 6) + (reg_num << 3) + 4 #4 = ESP
- sib = (scale_bits << 6) + (ind_reg << 3) + base_reg
- elif base_reg == 4: #4 = EBP
- rm = (disp_bits << 6) + (reg_num << 3) + base_reg
- sib = 0x24
- elif ind_reg >= 0:
- rm = (0 << 6) + (reg_num << 3) + 4 # 4 = ESP
- sib = (scale_bits << 6) + (ind_reg << 3) + 5 #5 = EBP
- elif base_reg >= 0:
- rm = (disp_bits << 6) + (reg_num << 3) + base_reg
- else:
- rm = (0 << 6) + (reg_num << 3) + 5 #5 = EBP
- if sib == -1:
- return "%02X" % rm
- else:
- return "%02X" % rm + "%02X" % sib
- def MemEncode16(reg_num, base_reg, ind_reg, n_dbytes):
- disp_bits = n_dbytes
- assert n_dbytes != 0 or base_reg != 13 or ind_reg >= 0
- if ind_reg < 0: # BX or BP
- parity = (13 - base_reg) >> 1 # 13 = BP
- else:
- parity = ind_reg - 14 # 14 = SI
- if ind_reg < 0 and base_reg < 0:
- mem_bits = 6
- rm = (reg_num << 3) + mem_bits
- else:
- if ind_reg < 0:
- mid_num = 3
- elif base_reg < 0:
- mid_num = 2
- else:
- mid_num = (base_reg - 11)>>1 # 11 = BX
- mem_bits = (mid_num << 1) + parity
- rm = (disp_bits << 6) + (reg_num << 3) + mem_bits
- return "%02X" % rm
- def ImmEncode(value, n_bytes):
- if n_bytes < 0:
- n_bytes = -n_bytes
- if value < 0:
- if n_bytes == 1:
- value = value + 256
- elif n_bytes == 2:
- value = value + 65536
- else:
- value = value + 0x100000000
- if n_bytes == 1:
- return "%02X" % value
- elif n_bytes == 2:
- return "%02X" % (value & 255) + "%02X" % (value >> 8)
- else:
- return "%02X" % (value & 255) + "%02X" % (255 &(value >> 8)) + "%02X" % (255 &(value >> 16)) + "%02X" % (value >> 24)
- ##################################################################
- #
- # Fetch Execute Section
- #
- ##################################################################
- #
- # Reading and Writing to Memory
- #
- def lg_read(segment_register, offset, n_bytes):
- # See Agarwal pp 73-74
- desc = descrVec[segment_register]
- if desc.Valid.getValue() and desc.Readable.getValue() and in_limits(desc, offset, n_bytes):
- return LA_read((desc.Base.getValue() + offset) & 0xffffffff , n_bytes)
- elif segment_register == SS:
- raise x86exception('fault', 12, 0, "Stack Fault")
- else:
- raise x86exception('fault', 13, 0, "General Protection Fault A")
- def lg_write(sreg,offset,value,n_bytes):
- # See Agarwal pp 79-80
- desc = descrVec[sreg]
- if desc.Valid.getValue() and desc.Writable.getValue() and in_limits(desc, offset, n_bytes):
- LA_write((desc.Base.getValue() + offset) & 0xffffffff, value, n_bytes)
- elif sreg == SS:
- raise x86exception('fault', 12, 0, "Stack Fault")
- else:
- raise x86exception('fault', 13, 0, "General Protection Fault B")
- mem.refresh()
- def in_limits(desc, offset, size):
- # See Agarwal p 78
- size = abs(size)
- if desc.ExpandDown.getValue():
- if desc.DefaultAttr.getValue():
- edLimit = 0xffffffff
- else:
- edLimit = 0xffff
- return offset > desc.Limit.getValue() and offset + size - 1 <= edLimit
- else:
- return offset + size - 1 <= desc.Limit.getValue()
- def LA_wrChk(laddr):
- # Not implemented yet
- return laddr
- def LA_rdChk(laddr):
- # p 93
- # Virtual to physical address translation occurs here
- #
- if laddr < 0 or laddr >= mem.length:
- print_feedback("Address: " + str(laddr))
- raise x86exception('fault', 100, -1,"Edlinas memory exceeded.")
- if ctrlReg[0].getValue() & 0x80000000 == 0: # PG flag
- return laddr
- else:
- raise x86exception('fault', 103, -1, "Not ready for paging.")
- err_code = int((CPL == 3) and 4)
- dir_table = ctrlReg[3].getValue() & 0xfffff000
- dir_table_offset = ((laddr >> 20) & 0xffc)
- dte = mem.read(dir_table + dir_table_offset, 4)
- if not dte & 1: # Present bit
- ctrlReg[2].setValue(laddr)
- raise x86exception('fault', 14, err_code, "page table not present")
- if CPL == 3 and dte & 4 == 0: # U_S bit
- ctrlReg[2].setValue(laddr)
- raise x86exception('fault', 14, err_code, "user supervisor bit") # PAGE
- if dte & 32 == 0: # Accessed bit
- mem.write(dir_table + dir_table_offset, dte | 32, 4)
- page_table = dte & 0xfffff000
- page_table_offset = (laddr >> 10) & 0xffc
- pte = mem.read(page_table + page_table_offset, 4)
- if not pte & 1: # Present bit
- ctrlReg[2].setValue(laddr)
- raise x86exception('fault', 14, err_code, "page not present") # PAGE
- if CPL == 3 and pte & 4 == 0: # U_S bit
- ctrlReg[2].setValue(laddr)
- raise x86exception('fault', 14, err_code, "user supervisor bit")
- if pte & 32 == 0: # Accessed bit
- mem.write(page_table + page_table_offset, dte | 32, 4)
- return (pte & 0xfffff000) | (laddr & 0xfff)
- def check_brkpt(btype, addr):
- # Not implemented yet
- # Code in TRAP.BAS
- return
- def LA_read(laddr, n_bytes):
- # Alignment check goes here.
- # print "LA_read(laddr = ", laddr
- m = abs(n_bytes)
- retv = 0
- for k in range(m):
- check_brkpt(3,laddr + k)
- phys_addr = LA_rdChk(laddr + k)
- retv = retv + (1 << (k<<3))* mem.read(phys_addr,1)
- modsize = 1 << (m << 3)
- if n_bytes < 0 and retv >= (modsize >> 1):
- retv = retv - modsize
- return retv
- def LA_write(laddr, value, n_bytes):
- assert laddr >= 0
- m = abs(n_bytes)
- assert m < 5
- if value < 0:
- value = (1<< (m << 3)) + value
- for k in range(m):
- check_brkpt(1,laddr + k)
- phys_addr = LA_rdChk(laddr + k)
- mem.write(phys_addr, value & 255, 1)
- value >>= 8
- def byte_swap(hex_string):
- assert type(hex_string) is str
- assert len(hex_string) % 2 == 0
- retval = ""
- for k in range(0,len(hex_string),2):
- retval = hex_string[k:k+2] + retval
- return retval
- def operand_size(n_bits, byte_flag):
- if byte_flag == 0:
- return 1
- if n_bits == 16:
- return 2
- return 4
- #####################################################################
- #
- # Segments
- #
- #####################################################################
- PROTECTED = 0
- REAL = 1
- VM86 = 2
- def mode():
- if ctrlReg[0].getValue() & 1 == 0 or archnum <= 2:
- return REAL
- else:
- return PROTECTED
- def in_limits(desc,off,size):
- if desc.ExpandDown.getValue():
- if desc.DefaultAttr.getValue():
- edLimit = 0xffffffff
- else:
- edLimit = 0xffff
- return (off > desc.Limit.getValue()) and (off + size - 1 <= edLimit)
- else:
- return (off + size - 1<= desc.Limit.getValue())
- def DTAB_write(err_code, desc, off, value):
- #p 81
- global CPL
- saveCPL = CPL
- if not desc.Valid or not in_limits(desc, off, 1):
- raise x86exception('fault', 13, (err_code & -4)) # GP
- CPL = 0
- LA_write(desc.Base.getValue() + off, value,1 )
- CPL = saveCPL
- def DTAB_read(err_code, desc, offset, TSS_load, n_bytes):
- # pp 74-75
- global CPL
- if not desc.Valid or not desc.Readable or not in_limits(desc, offset, n_bytes):
- if TSS_load:
- raise x86exception('fault', 10, (err_code & -4)) # TASK
- else:
- raise x86exception('fault', 13, (err_code & -4)) # GP
- saveCPL = CPL
- CPL = 0
- retval = LA_read(desc.Base.getValue() + offset, n_bytes)
- CPL = saveCPL
- return retval
- def mark_accessed(sel):
- # p 66
- if sel & 4 == 0:
- tableDesc = descrVec[GDT]
- else:
- tableDesc = descrVec[LDT]
- d2 = DTAB_read(sel, tableDesc, sel & 0xfff8 + 5, False,1)
- DTAB_write(sel, tableDesc, sel & 0xfff8 + 5, d2|1, False, 1)
- #def nullSel(sel):
- # p 67
- # return (sel < 4)
- def load_data_seg(sel, desc, TSS_load):
- # Data segment descriptor desc is written into.
- # p 71
- if sel < 4 : # nullSel(sel)
- desc.Valid.setValue(False) #See p67
- return
- #lock Descriptor Table
- desc.read_descr(sel, TSS_load)
- if(((desc.Readable.getValue() or desc.Writable.getValue()) and \
- not desc.Conforming.getValue() and desc.DPL.getValue()>=CPL and \
- desc.DPL.getValue() >= (sel & 3))or \
- (desc.Readable.getValue() and desc.Conforming.getValue())):
- if not desc.Valid.getValue():
- raise x86exception('fault',11, sel & 0xFFFC)
- elif TSS_load:
- raise x86exception('fault',10, sel & 0xFFFC) # TASK
- else:
- raise x86exception('fault',13, sel & 0xFFFC) # GP
- mark_accessed(sel)
- class x86exception(Exception):
- def __init__(self,xcpclass, interrupt_number,error_code,error_message):
- #
- # Python user defined exceptions are used in place of "signal_fault", etc.
- # The xcpclass is either 'fault', 'trap', 'imprecise', or 'abort'.
- #
- # x86 Exceptions are listed on page 154.
- # The name of the exception is included in the error_message.
- # An error_code of -1 is used if there is no error code.
- #
- # An interrupt number of 100 is used when the edlinas machine has an error.
- #
- self.args = (xcpclass, interrupt_number,error_code,error_message)
- self.xcpclass = xcpclass
- self.interrupt_number = interrupt_number
- self.error_code = error_code
- self.error_message = error_message
- #
- #
- # This is the processor's Fetch and Execute definition
- #
- def fetchexec():
- byte = fetch_code(1)
- prefix = {}
- while prefixcheck(byte,prefix):
- byte = fetch_code(1)
- sreg = prefix.get('segmentoverride', -1)
- if "OS" in prefix:
- os = 48 - Use_size.get()
- else:
- os = Use_size.get()
- if "AS" in prefix:
- ads = 48 - Use_size.get()
- else:
- ads = Use_size.get()
- if sreg == FS or sreg == GS and archnum < 3:
- raise x86exception('fault', 6, -1,"Invalid prefix")
- if 'lock' in prefix:
- lock_flag = 1
- else:
- lock_flag = 0
- hb1 = byte >> 4
- hb2 = byte & 15
- instruction_recognized = True
- if hb1 < 4 and (hb2 & 7) < 6:
- DoAlu(byte>>3,byte & 7,sreg,ads,os,lock_flag)
- elif hb1 == 8 and hb2 < 4:
- if hb2 == 2:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- AluMI(byte, sreg, ads, os,lock_flag)
- elif hb1 == 8 and (hb2 >> 1) == 3:
- DoXch(byte,sreg,ads,os, lock_flag)
- elif byte == 0x0f:
- Do0F(sreg,ads,os,lock_flag)
- elif lock_flag == 1:
- raise x86exception('fault', 6, -1,"Instruction not lockable")
- elif hb1 < 2 and byte & 7 == 6:
- DoPush(byte,os)
- elif hb1 < 2 and byte & 7 == 7:
- DoPop(byte,sreg,ads,os)
- elif hb1 < 4 and byte & 7 == 7:
- DoAacrap(byte)
- elif hb1 == 4 :
- DoIncDec(byte,os)
- elif hb1 == 5:
- if hb2 < 8:
- DoPush(byte,os)
- else:
- DoPop(byte,sreg,ads,os)
- elif hb1 == 6 and hb2 == 0:
- DoPusha(os)
- elif hb1 == 6 and hb2 == 1:
- Popa(os)
- elif hb1 == 6 and hb2 == 2:
- DoBound(sreg,ads,os)
- elif hb1 == 6 and hb2 == 3:
- DoArpl(sreg,ads,os)
- elif hb1 == 6 and (hb2 == 8 or hb2 == 0xa):
- DoPush(byte,os)
- elif hb1 == 6 and (hb2 == 9 or hb2 == 0xb):
- DoImul3(byte,sreg,ads,os)
- elif hb1 == 6 and hb2 > 0xb:
- DoString(byte,ads,os)
- elif hb1 == 7:
- DoJcond(byte,os)
- elif hb1 == 8 and hb2 < 6:
- DoTest(byte,sreg,ads,os)
- elif hb1 == 8 and 7 < hb2 < 0xc:
- DoMov(byte,sreg,ads,os)
- elif hb1 == 8 and hb2 == 0xd:
- DoLea(sreg,ads,os)
- elif hb1 == 8 and (hb2 == 0xc or hb2 == 0xe):
- DoMovs(byte,sreg,ads,os)
- elif byte == 0x8f:
- DoPop(byte,sreg,ads,os)
- elif hb1 == 9 and hb2 == 0:
- pass
- elif hb1 == 9 and hb2 < 8:
- DoXch(byte,sreg,ads,os, lock_flag)
- elif hb1 == 9 and hb2 < 0xa:
- DoConv(byte, os)
- elif byte == 0x9a or byte == 0xe8:
- DoCall(byte,os)
- elif byte == 0x9c:
- Pushf(os)
- elif byte == 0x9d:
- Popf(os)
- elif byte == 0x9e:
- DoSahf()
- elif byte == 0x9f:
- DoLahf()
- elif hb1 == 0xa and hb2 < 4:
- DoMovaI(byte, sreg, os)
- elif hb1 == 0xa and 7 < hb2 < 0xa:
- DoTest(byte,sreg,ads,os)
- elif hb1 == 0xa:
- if 'repeat' in prefix:
- signal.pending_repeat = prefix['repeat']
- DoString(byte,ads,os)
- elif hb1 == 0xb:
- DoMovrI(byte,os)
- elif hb1 == 0xc and 3 < hb2 < 6:
- DoLodSeg(byte, os)
- elif hb1 == 0xc and 5 < hb2 < 8:
- DoMovmI(byte, ads, os)
- elif hb1 == 0xc and hb2 == 8:
- DoEnter(os)
- elif hb1 == 0xc and hb2 == 9:
- DoLeave(os)
- elif hb1 == 0xc and hb2 == 0xc:
- raise x86exception('trap', 3, -1,"Breakpoint interrupt")
- elif hb1 == 0xc and hb2 == 0xd:
- DoInt()
- elif hb1 == 0xc and hb2 == 0xe:
- DoInto()
- elif hb1 == 0xe and hb2 < 4:
- raise x86exception('fault', 101, -1,"Instruction not implemented")
- DoLoop()
- elif hb1 == 0xe and hb2&7 > 3:
- DoInOut(byte,ads, os)
- elif hb1 == 0xe:
- DoJmp(byte, os)
- elif (hb1 == 0xc and hb2 < 2) or (hb1 == 0xd and hb2 < 4):
- DoShift(byte,sreg,ads,os)
- elif hb1 == 0xc and (hb2 & 6) == 2:
- if prog.call_depth == 0:
- print_feedback("Program finished. ")
- prog.set_execstate('interpreting')
- save_EIP = EIP.getvalue()
- prog.set_current_inst(instoffset = save_EIP)
- return
- else:
- prog.call_depth = prog.call_depth -1
- DoRet(byte, os)
- elif hb1 == 0xd and 3 < hb2 < 6:
- DoAacrap(byte)
- elif hb1 == 0xd and hb2 == 7:
- Xlat(byte, ads)
- elif byte == 0xf4:
- if CPL == 0:
- prog.set_execstate('stepping') # Supposed to wait here for interrupts
- else:
- raise x86exception('fault', 13, 0, "General Protection Fault Y")
- elif byte == 0xf5: # CMC
- Flags["CF"].setValue(1 - Flags["CF"].getValue())
- elif hb1 == 0xf and (hb2 >> 1) == 3:
- DoUnM(byte,sreg,ads,os)
- elif byte == 0xf8:
- Flags["CF"].setValue(0)
- elif byte == 0xf9:
- Flags["CF"].setValue(1)
- elif byte == 0xfa:
- if mode() == REAL:
- Flags["IF"].setValue(0)
- elif mode() == PROTECTED and CPL.getValue() <= IOPL.getValue():
- Flags["IF"].setValue(0)
- elif mode() == VM86 and IOPL.getValue() == 3:
- Flags["IF"].setValue(0)
- else:
- raise x86exception('fault', 13, 0, "General Protection Fault X")
- elif byte == 0xfb:
- if mode() == REAL:
- Flags["IF"].setValue(1)
- elif mode() == PROTECTED and CPL.getValue() <= IOPL.getValue():
- Flags["IF"].setValue(1)
- elif mode() == VM86 and IOPL.getValue() == 3:
- Flags["IF"].setValue(1)
- else:
- raise x86exception('fault', 13, 0, "General Protection Fault X")
- elif byte == 0xfc:
- Flags["DF"].setValue(0)
- elif byte == 0xfd:
- Flags["DF"].setValue(1)
- elif hb1 == 0xf and (hb2 == 0xe or hb2 == 0xf):
- DoFEFF(byte,sreg,ads,os,lock_flag)
- else:
- print("byte = ", "%02X" % byte)
- raise x86exception('fault', 101, -1,"Instruction not implemented")
- # raise x86exception('fault', 6, -1,"Invalid instruction")
- if prog.execstate != 'blocked':
- prog.set_current_inst(instoffset = EIP.getvalue() - prog.load_origin)
- return
- def Do0F(sreg,ads,os,lock_flag):
- # Second Hop Op Codes 0F
- byte2 = fetch_code(1)
- hb1 = byte2 >> 4
- hb2 = byte2 & 15
- if hb1 == 0xc and hb2 < 2:
- DoXadd(byte2,sreg,ads,os,lock_flag)
- elif lock_flag:
- raise x86exception('fault', 101, -1,"Instruction not implemented")
- elif hb1 == 0 and hb2 < 2:
- Do0F01(byte2,ads,os)
- elif hb1 == 0 and hb2 == 6: # CLTS
- if CPL != 0:
- raise x86exception('fault', 13, 0, "General Protection Fault C")
- ctrlReg[0].setValue(ctrlReg[0].getValue() & 0xfffffff7)
- elif hb1 == 0 and hb2 == 8: # INVD
- pass
- elif hb1 == 0 and hb2 == 9: # WBINVD
- pass
- elif hb1 == 2 and hb2 < 7:
- DoMovt(byte2)
- elif hb1 == 6:
- pass
- elif hb1 == 8 and archnum > 2:
- DoJcond(byte2, os)
- elif hb1 == 9:
- Setcond(hb2,sreg,ads)
- elif hb1 == 0xa and hb2 & 7 == 0:
- DoPush(byte2,sreg,ads,os)
- elif hb1 == 0xa and hb2 & 7 == 1:
- DoPop(byte2,sreg,ads,os)
- elif hb1 == 0xa and hb2 == 0xf:
- DoImul3(byte2,sreg,ads,os)
- elif hb1 == 0xa and hb2 == 2:
- DoCpuid()
- elif hb1 == 0xa and hb2 < 4:
- raise x86exception('fault', 101, -1,"Instruction not implemented")
- elif hb1 == 0xa and (hb2 == 4 or hb2 == 5 or hb2 == 0xc or hb2 == 0xd):
- DoShift(byte2,sreg,ads,os)
- elif hb1 == 0xa and (hb2 == 3 or hb2 == 0xb):
- DoBits(byte2,sreg,ads,os,lock_flag)
- elif hb1 == 0xb and hb2 < 2:
- raise x86exception('fault', 101, -1,"Instruction not implemented")
- DoCmpXch(byte2,sreg,ads,os)
- elif hb1 == 0xb and (hb2 == 4 or hb2 == 5):
- DoLodSeg(byte2, os)
- elif hb1 == 0xb and hb2 & 7 > 5:
- DoMovx(byte2,sreg,ads,os)
- elif hb1 == 0xb and (hb2 == 3 or hb2 == 0xa or hb2 == 0xb):
- DoBits(byte2,sreg,ads,os,lock_flag)
- elif hb1 == 0xb and (0xb < hb2 < 0xe):
- DoBitScan(byte2,sreg,ads,os,lock_flag)
- elif hb1 == 0xc and hb2 > 7:
- DoBswap(byte2)
- else:
- raise x86exception('fault', 101, -1,"Instruction not implemented")
- def Do0F01(byte2,ads,os):
- n_bytes = operand_size(os, byte & 1)
- modrm_byte = fetch_code(1)
- reg_bits = (modrm_byte >> 3)&7
- rm_bits = modrm_byte & 7
- source = regCode(reg_bits, n_bytes)
- op2 = regFetch(source)
- temp = op2
- if modrm_byte >= 0xc0:
- dest = regCode(rm_bits, n_bytes)
- op1 = regFetch(dest)
- else:
- (sreg, offset) = GetOffset(modrm_byte,ads,sreg)
- op1 = lg_read(sreg, offset, n_bytes)
- if byte2 == 0 and reg_bits == 0: # SLDT
- if mode() != PROTECTED:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- sel = segReg[LDT].getValue()
- if modrm_byte >= 0xc0:
- regStore(dest,sel)
- else:
- lg_write(sreg, offset, sel, 2)
- elif byte2 == 0 and reg_bits == 1: # STR
- if mode() != PROTECTED:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- sel = segReg[TSS].getValue()
- if modrm_byte >= 0xc0:
- regStore(dest,sel)
- else:
- lg_write(sreg, offset, sel, 2)
- elif byte2 == 0 and reg_bits == 2: # LLDT
- if mode() != PROTECTED:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- if CPL != 0:
- raise x86exception('fault', 13, 0, "General Protection Fault D")
- if modrm_byte >= 0xc0:
- sel = regFetch(dest)
- else:
- sel = lg_read(sreg, offset, 2)
- if sel & 4:
- raise x86exception('fault', 13, sel & 0xFFFC, "General Protection FaultE")
- if sel < 4: # Is it the Null selector
- descrVec[LDT].Valid = False
- else:
- descrVec[LDT].read_descr(sel, False)
- if descrVec[LDT].Type != 2: # LDT_SEG type
- raise x86exception('fault', 13, sel & 0xFFFC, "General Protection FaultF")
- if not descrVec[LDT].Valid:
- raise x86exception('fault', 13, sel & 0xFFFC, "General Protection FaultG")
- segReg[LDT].setValue(sel)
- elif byte2 == 0 and reg_bits == 3: # LTR
- if mode() != PROTECTED:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- if CPL != 0:
- raise x86exception('fault', 13, 0, "General Protection Fault H")
- if modrm_byte >= 0xc0:
- sel = regFetch(dest)
- else:
- sel = lg_read(sreg, offset, 2)
- if sel < 4 or sel & 4 :
- raise x86exception('fault', 13, sel & 0xFFFC, "General Protection Fault I")
- descrVec[TSS].read_descr(sel, False)
- if descrVec[TSS].Type == 1 or descrVec[TSS] == 9: # Not Busy 16 or 32 bit TSS
- if not descrVec[TSS].Valid:
- raise x86exception('fault', 11, sel & 0xFFFC, "Not Present Fault")
- temp = DTAB_read(sel,descrVec[GDT],(sel & 0xfff8 + 5), False, 1)
- DTAB_write(sel,descrVec[GDT],(sel & 0xfff8 + 5), temp | 2, False, 1)
- segReg[TSS].setValue(sel)
- elif byte2 == 0 and reg_bits == 4: # VERR
- if mode() != PROTECTED:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- if modrm_byte >= 0xc0:
- sel = regFetch(dest)
- else:
- sel = lg_read(sreg, offset, 2)
- if sel < 4 or not in_limits(tab_desc, sel & 0xfff8, 8):
- Flags["ZF"].setValue(0)
- else:
- dsc = Descr()
- dsc.read_descr(sel, False)
- if(((dsc.Readable or dsc.Writable) and CPL <= dsc.DPL and (sel & 3)<= dsc.DPL)or
- (dsc.Executable and dsc.Readable and CPL <= dsc.DPL and (sel & 3)<= dsc.DPL)or
- (dsc.Conforming and dsc.Readable)):
- Flags["ZF"].setValue(1)
- else:
- Flags["ZF"].setValue(0)
- elif byte2 == 0 and reg_bits == 5: # VERW
- if mode() != PROTECTED:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- if modrm_byte >= 0xc0:
- sel = regFetch(dest)
- else:
- sel = lg_read(sreg, offset, 2)
- if sel & 4:
- tab_desc = descrVec[LDT]
- else:
- tab_desc = descrVec[GDT]
- if sel < 4 or not in_limits(tab_desc, sel & 0xfff8, 8):
- Flags["ZF"].setValue(0)
- else:
- dsc = Descr()
- dsc.read_descr(sel, False)
- if dsc.Writable and CPL <= dsc.DPL and (sel & 3)<= dsc.DPL:
- Flags["ZF"].setValue(1)
- else:
- Flags["ZF"].setValue(0)
- elif byte2 == 0:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- elif byte2 == 1 and reg_bits == 0: # SGDT
- lg_write(sreg, offset, descrVec[GDT].Limit.getValue(), 2)
- if os == 32:
- lg_write(sreg, offset + 2, descrVec[GDT].Base.getValue() , 4)
- else:
- lg_write(sreg, offset + 2, descrVec[GDT].Base.getValue() & 0xffffff, 2)
- elif byte2 == 1 and reg_bits == 1: # SIDT
- lg_write(sreg, offset, descrVec[IDT].Limit.getValue(), 2)
- if os == 32:
- lg_write(sreg, offset + 2, descrVec[IDT].Base.getValue() , 4)
- else:
- lg_write(sreg, offset + 2, descrVec[IDT].Base.getValue() & 0xffffff, 2)
- elif byte2 == 1 and reg_bits == 2: # LGDT
- if CPL != 0:
- raise x86exception('fault', 13, 0, "General Protection Fault J")
- if modrm_byte >= 0xc0:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- descrVec[GDT].Limit.setValue(lg_read(sreg, offset,2))
- if os == 32:
- descrVec[GDT].Base.setValue(lg_read(sreg, offset + 2, 4))
- else:
- descrVec[GDT].Base.setValue(lg_read(sreg, offset + 2, 2) & 0xFFFFFF)
- descrVec[GDT].Valid.setValue(True)
- elif byte2 == 1 and reg_bits == 3: # LIDT
- if CPL != 0:
- raise x86exception('fault', 13, 0, "General Protection Fault K")
- descrVec[IDT].Limit.setValue(lg_read(sreg, offset,2))
- if os == 32:
- descrVec[IDT].Base.setValue(lg_read(sreg, offset + 2, 4))
- else:
- descrVec[IDT].Base.setValue(lg_read(sreg, offset + 2, 2) & 0xffffff)
- # descrVec[IDT].Valid = True
- elif byte2 == 1 and reg_bits == 5: # SMSW
- msw = ctrlReg[0].getValue() & 31
- if modrm_byte >= 0xc0:
- regStore(dest, msw)
- else:
- lg_write(sreg, offset, msw, 2)
- elif byte2 == 1 and reg_bits == 6: # LMSW
- if CPL != 0:
- raise x86exception('fault', 13, 0, "General Protection Fault L")
- if modrm_byte >= 0xc0:
- msm = regFetch(dest)
- else:
- msm = lg_read(sreg, offset, 2)
- msw = msm & 31
- if ctrlReg[0].getValue() & 1 == 0:
- ctrlReg[0].setValue(msm)
- else:
- msm = msm | 1
- ctrlReg[0].setValue(msm)
- elif byte2 == 1 and reg_bits == 7: # INVPLG
- pass
- else:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- def fetch_code(n_bytes):
- n = abs(n_bytes)
- if EIP.getvalue() < -1:
- b = 2*(EIP.getvalue() - prog.store_origin)
- retval= int(byte_swap(prog.stored_command[b:b+2*n]),16)
- if n_bytes < 0 and retval >= (1 << ((n << 3) - 1)):
- retval = retval - (1 << (n << 3))
- else:
- retval = LA_read(EIP.getvalue(), n_bytes)
- EIP.setvalue(EIP.getvalue() + n)
- return retval
- def prefixcheck(byte, prefdict={}):
- if byte == 0x2e:
- prefdict['segmentoverride'] = CS
- elif byte == 0x3e:
- prefdict['segmentoverride'] = DS
- elif byte == 0x26:
- prefdict['segmentoverride'] = ES
- elif byte == 0x64:
- prefdict['segmentoverride'] = FS
- elif byte == 0x65:
- prefdict['segmentoverride'] = GS
- elif byte == 0x36:
- prefdict['segmentoverride'] = SS
- elif byte == 0x66:
- prefdict["OS"] = "OS"
- elif byte == 0x67:
- prefdict["AS"] = "AS"
- elif byte == 0xf3:
- prefdict['repeat'] = 'REPE' #REPE
- elif byte == 0xf2:
- prefdict['repeat'] = 'REPNE' #REPNE
- elif byte == 0xf0:
- prefdict['lock'] = "LOCK"
- else:
- return False
- def regStore(reg_num, value):
- assert value >= 0
- if reg_num < 8:
- genReg[reg_num].setValue(value)
- elif reg_num < 16:
- full_value = genReg[reg_num - 8].getValue()
- genReg[reg_num - 8].setValue((full_value&-65536)|value)
- elif reg_num < 20:
- full_value = genReg[reg_num - 16].getValue()
- genReg[reg_num - 16].setValue((full_value&-256)|value)
- elif reg_num < 24:
- full_value = genReg[reg_num - 20].getValue()
- genReg[reg_num - 20].setValue((full_value & (-65536|255))|(value<<8))
- elif reg_num < 32:
- segReg[reg_num - 24].setValue(value)
- elif reg_num < 40:
- debReg[reg_num - 32].setValue(value)
- elif reg_num < 48:
- testReg[reg_num - 40].setValue(value)
- elif reg_num < 52:
- ctrlReg[reg_num - 48].setValue(value)
- else:
- raise ValueError("Bad register number: " + str(reg_num))
- if reg_num == 4 or reg_num == 12:
- try:
- stackWindow
- isdefined = True
- except:
- isdefined = False
- if isdefined and stackWindow.winfo_exists():
- stackView.refresh()
- def regFetch(reg_num):
- if reg_num < 8:
- retval = genReg[reg_num].getValue()
- elif reg_num < 16:
- retval = 0xffff & genReg[reg_num - 8].getValue()
- elif reg_num < 20:
- retval = 0xff & genReg[reg_num -16].getValue()
- elif reg_num < 24:
- retval = (0xff00 & genReg[reg_num - 20].getValue()) >> 8
- elif reg_num < 32:
- retval = segReg[reg_num - 24].getValue()
- elif reg_num < 40:
- retval = debReg[reg_num - 32].getValue()
- elif reg_num < 48:
- retval = testReg[reg_num - 40].getValue()
- elif reg_num < 52:
- retval = ctrlReg[reg_num - 48].getValue()
- else:
- raise ValueError("not defined for reg_num = " + str(reg_num))
- return retval
- def reg_signedFetch(reg_num):
- # This function is never called.
- unsigned_val = regFetch(reg_num)
- if reg_num < 8:
- if unsigned_val > 0x7fffffff:
- return unsigned_val - 0x100000000
- else:
- return unsigned_val
- elif reg_num < 16:
- if unsigned_val > 32767:
- return unsigned_val - 65536
- else:
- return unsigned_val
- elif reg_num < 24:
- if unsigned_val > 127:
- return unsigned_val - 256
- else:
- return unsigned_val
- raise ValueError("Only registers numbered below 24 can have a sign.")
- def regCode(reg_num,S):
- """ reg_num is a number less than 8 S
- The return codes follow:
- 0- 7: EAX ECX EDX EBX ESP EBP ESI EDI 4
- 8-15: AX CX DX BX SP BP SI DI 2
- 16-23: AL CL DL BL AH CH DH BH 1
- 24-31: ES CS SS DS FS GS LDT TSS 5
- 32-39: DR0 DR1 DR2 DR3 DR4 DR5 DR6 DR7 6
- 40-47: TR0 TR1 TR2 TR3 TR4 TR5 TR6 TR7 7
- 48-51: CR0 CR1 CR2 CR3 8 """
- assert S > 0
- if S == 1:
- return reg_num + 16
- if S == 2:
- return reg_num + 8
- if S == 4:
- return reg_num
- return reg_num + (S - 2) * 8
- def getFlags(n_bytes):
- retval = 0
- retval = retval + (Flags["CF"].getValue()<< 0)
- retval = retval + (1<< 1)
- retval = retval + (Flags["PF"].getValue()<< 2)
- retval = retval + (0<< 3)
- retval = retval + (Flags["AF"].getValue()<< 4)
- retval = retval + (0<< 5)
- retval = retval + (Flags["ZF"].getValue()<< 6)
- retval = retval + (Flags["SF"].getValue()<< 7)
- retval = retval + (Flags["TF"].getValue()<< 8)
- retval = retval + (Flags["IF"].getValue()<< 9)
- retval = retval + (Flags["DF"].getValue()<< 10)
- retval = retval + (Flags["OF"].getValue()<< 11)
- retval = retval + (IOPL.getValue()<< 12) # 2 bit value
- retval = retval + (Flags["NT"].getValue()<< 14)
- retval = retval + (0<< 15)
- if n_bytes == 2:
- return retval
- retval = retval + (Flags["RF"].getValue()<< 16)
- retval = retval + (Flags["VM"].getValue()<< 17)
- retval = retval + (Flags["AC"].getValue()<< 18)
- return retval
- def setFlags(value, n_bytes):
- Flags["CF"].setValue((value>> 0) & 1)
- Flags["PF"].setValue((value>> 2) & 1)
- Flags["AF"].setValue((value>> 4) & 1)
- Flags["ZF"].setValue((value>> 6) & 1)
- Flags["SF"].setValue((value>> 7) & 1)
- Flags["TF"].setValue((value>> 8) & 1)
- Flags["IF"].setValue((value>> 9) & 1)
- Flags["DF"].setValue((value>> 10) & 1)
- Flags["OF"].setValue((value>> 11) & 1)
- IOPL.setValue((value>> 12) & 3) # 2 bit value
- Flags["NT"].setValue((value>> 14) & 1)
- if n_bytes == 2:
- return
- Flags["RF"].setValue((value>> 16) & 1)
- Flags["VM"].setValue((value>> 17) & 1)
- Flags["AC"].setValue((value>> 18) & 1)
- def GetOffset(modrm_byte, address_size = 32, seg_reg = -1):
- assert modrm_byte < 0xc0
- default_segment_register = 3 # DS
- rm_num = modrm_byte & 7
- row_num = (modrm_byte >> 6) + 1
- if address_size == 32:
- if rm_num == 4:
- sreg, get = GetSibAdd(row_num)
- default_segment_register = sreg
- elif rm_num == 5 and row_num == 1:
- get = fetch_code(4)
- else:
- if row_num == 1:
- get = 0
- elif row_num == 2:
- get = fetch_code(1)
- if get > 127:
- get = get -256 + (1 << 32)
- elif row_num == 3:
- get = fetch_code(4)
- if rm_num == 5: # EBP
- default_segment_register = 2 #Segment register = SS
- elif rm_num == 7: # EDI
- default_segment_register = 0 #Segment register = ES
- get = get + regFetch(rm_num)
- if get > 0xffffffff:
- get = get & 0xffffffff
- elif address_size == 16:
- if rm_num == 6 and row_num == 1:
- get = fetch_code(2)
- elif row_num == 2:
- get = fetch_code(1)
- if get > 127:
- get = get -256 + (1 << 32) # 1<< 16?
- elif row_num == 3:
- get = fetch_code(2)
- else:
- get = 0
- if rm_num == 0:
- get = get + regFetch(11) + regFetch(14) # BX + SI
- elif rm_num == 1:
- get = get + regFetch(11) + regFetch(15) # BX + DI
- elif rm_num == 2:
- get = get + regFetch(13) + regFetch(14) # BP + SI
- default_segment_register = 2 #Segment register = SS
- # segreg = SS
- elif rm_num == 3:
- get = get + regFetch(13) + regFetch(15) # BP + DI
- default_segment_register = 2 #Segment register = SS
- elif rm_num == 4:
- get = get + regFetch(14) # SI
- elif rm_num == 5:
- get = get + regFetch(15) # DI
- elif rm_num == 6:
- get = get + regFetch(13) # BP
- default_segment_register = 2 #Segment register = SS
- elif rm_num == 7:
- get = get + regFetch(11) # BX
- get = get & 0xffff
- if seg_reg == -1:
- return (default_segment_register, get)
- else:
- return (seg_reg, get)
- def GetSibAdd(row_num):
- sreg = 3 # DS
- sib_byte = fetch_code(1)
- scale = 1 << (sib_byte >> 6)
- base_reg_num = sib_byte & 7
- ind_reg_num = (sib_byte>> 3) & 7
- if ind_reg_num == 4:
- if base_reg_num == 4 and scale == 1:
- scale = 0
- else:
- raise x86exception('fault', 6, -1,"Invalid SIB byte")
- if base_reg_num == 5 and row_num == 1:
- base_address = fetch_code(4)
- elif base_reg_num in [4,5]:
- sreg = 2 #Segment register = SS
- base_address = regFetch(base_reg_num)
- else:
- base_address = regFetch(base_reg_num)
- if row_num == 1:
- sib_address = base_address + scale * regFetch(ind_reg_num)
- elif row_num == 2:
- imm_num = fetch_code(1)
- if imm_num > 127:
- sib_address= base_address + scale * regFetch(ind_reg_num)+ imm_num - 256
- else:
- sib_address= base_address + scale * regFetch(ind_reg_num)+ imm_num
- elif row_num == 3:
- sib_address= base_address + scale * regFetch(ind_reg_num)+ fetch_code(4)
- if sib_address < 0:
- sib_address = sib_address + (1<< 32)
- elif sib_address > 0xffffffff:
- sib_address = sib_address & 0xffffffff
- return (sreg, sib_address)
- def DoAacrap(byte):
- # Handles opcodes 27, 2f, 37, 3f, d4, and d5
- if byte == 0x37: #AAA
- x = regFetch(16) # AL
- if Flags["AF"].getValue() == 1 or (x & 15) > 9:
- x = (x + 6) & 0xf
- regStore(16, x) # AL
- y = regFetch(20) # AH
- regStore(20, y + 1) # AH
- Flags["AF"].setValue(1)
- else:
- Flags["AF"].setValue(0)
- Flags["CF"].setValue(Flags["AF"].getValue())
- elif byte == 0x3f: #AAS
- x = regFetch(16) # AL
- if Flags["AF"].getValue() == 1 or (x & 15) > 9:
- # x = (x - 6) & 0xf
- x = (x & 0xf) - 6
- regStore(16, x) # AL
- y = regFetch(20) # AH
- y = (y - 1) & 0xf
- regStore(20, y) # AH
- Flags["AF"].setValue(1)
- else:
- Flags["AF"].setValue(0)
- Flags["CF"].setValue(Flags["AF"].getValue())
- elif byte == 0x27: #DAA
- x = regFetch(16) # AL
- if Flags["AF"].getValue() == 1 or (x & 15) > 9:
- x = x + 6
- regStore(16, x) # AL
- Flags["AF"].setValue(1)
- else:
- Flags["AF"].setValue(0)
- if Flags["CF"].getValue() == 1 or (x & 0xf0) > 0x90:
- regStore(16, x + 0x60) # AL
- Flags["CF"].setValue(1)
- else:
- Flags["CF"].setValue(0)
- elif byte == 0x2f: #DAS
- x = regFetch(16) # AL
- if Flags["AF"].getValue() == 1 or (x & 15) > 9:
- x = x - 6
- regStore(16, x) # AL
- Flags["AF"].setValue(1)
- else:
- Flags["AF"].setValue(0)
- if Flags["CF"].getValue() == 1 or (x & 0xf0) > 0x90:
- regStore(16, x - 0x60) # AL
- Flags["CF"].setValue(1)
- else:
- Flags["CF"].setValue(0)
- elif byte == 0xd4: #AAM
- x = regFetch(16) #AL
- y = (fetch_code(1) or 10)
- regStore(20, x//y) #AH
- regStore(16, x % y)
- elif byte == 0xd5: #AAD
- # regFetch(16) = AL
- y = (fetch_code(1) or 10)
- x = (regFetch(20) * y + regFetch(16)) & 0xff
- regStore(16,x)
- regStore(20,0)
- #Common flag settings
- if regFetch(16) & 0x80 == 0: #AL
- Flags["SF"].setValue(0)
- else:
- Flags["SF"].setValue(1)
- if x == 0:
- Flags["ZF"].setValue(1)
- else:
- Flags["ZF"].setValue(0)
- Flags["PF"].setValue(evenParity(regFetch(16))) #AL
- def DoAlu(oper_num,opand_num,sreg,ads,n_bits,lock_flag=0):
- n_bytes = operand_size(n_bits,opand_num & 1)
- if opand_num & 1 == 0:
- n_bits = 8
- if opand_num >> 1 == 2: # Dest = EAX, AX, or AL; Source = imm
- dest = regCode(0,n_bytes)
- op1 = regFetch(dest)
- op2 = fetch_code(n_bytes)
- if lock_flag:
- raise x86exception('fault', 6, -1, "Not lockable")
- elif opand_num >> 1 == 1: # Dest = r; Source = rmv or rmb
- modrm_byte = fetch_code(1)
- dest = regCode((modrm_byte>>3)&7,n_bytes)
- op1 = regFetch(dest)
- if modrm_byte >= 0xc0:
- source = regCode(modrm_byte & 7,n_bytes)
- op2 = regFetch(source)
- if lock_flag:
- raise x86exception('fault', 6, -1, "Not lockable")
- else:
- sreg,offset = GetOffset(modrm_byte,ads,sreg)
- op2 = lg_read(sreg,offset,n_bytes)
- elif opand_num >> 1 == 0: # Dest = rmv or rmb; Source = r
- modrm_byte = fetch_code(1)
- source = regCode((modrm_byte>>3)&7,n_bytes)
- op2 = regFetch(source)
- if modrm_byte >= 0xc0:
- dest = regCode(modrm_byte & 7,n_bytes)
- op1 = regFetch(dest)
- if lock_flag:
- raise x86exception('fault', 6, -1, "Not lockable")
- else:
- sreg,offset = GetOffset(modrm_byte,ads,sreg)
- op1 = lg_read(sreg,offset,n_bytes)
- else:
- return
- if oper_num == 0:
- op1 = sum(op1,op2,n_bits)
- elif oper_num in [1,4,6]:
- op1 = bblog(op1,op2,oper_num,n_bits)
- elif oper_num == 2:
- op1 = sum(op1,op2,n_bits,carry_flag=Flags["CF"].getValue())
- elif oper_num == 3:
- op1 = dif(op1,op2,n_bits,carry_flag=Flags["CF"].getValue())
- elif oper_num == 5:
- op1 = dif(op1,op2,n_bits)
- elif oper_num == 7:
- dif(op1,op2,n_bits)
- if opand_num >> 1 == 0 and modrm_byte < 0xc0: # Dest = rmv or rmb; Source = r
- lg_write(sreg,offset,op1,n_bytes)
- else:
- regStore(dest,op1)
- def AluMI(byte, sgrg, ads, os,lock_flag):
- n_bytes = operand_size(os, byte & 1)
- if byte == 0x83:
- n_imm_bytes = 1
- else:
- n_imm_bytes = n_bytes
- byte = fetch_code(1)
- reg_bits = (byte >> 3) & 7
- mem_bits = byte & 7
- if byte >= 0xc0 and lock_flag == 1:
- raise x86exception('fault', 6, -1,"Lock Invalid")
- elif byte >= 0xc0:
- dest = regCode(mem_bits, n_bytes)
- mem_num = regFetch(dest)
- else:
- sreg,offset = GetOffset(byte, seg_reg=sgrg)
- mem_num = lg_read(sgrg,offset,n_bytes)
- imm_num = fetch_code(n_imm_bytes)
- if reg_bits == 0:
- result = sum(mem_num, imm_num,n_bytes << 3, 0)
- elif reg_bits == 1 or reg_bits == 4 or reg_bits == 6:
- result = bblog(mem_num, imm_num, reg_bits, n_bytes<< 3)
- elif reg_bits == 2:
- result = sum(mem_num, imm_num, n_bytes << 3, Flags["CF"].getValue())
- elif reg_bits == 3:
- result = dif(mem_num, imm_num, n_bytes << 3, Flags["CF"].getValue())
- elif reg_bits == 5:
- result = dif(mem_num, imm_num, n_bytes << 3, 0)
- elif reg_bits == 7:
- dif(mem_num, imm_num,n_bytes<< 3, 0)
- result = mem_num
- if byte >= 0xc0:
- regStore(dest, result)
- else:
- lg_write(sgrg,offset,result,n_bytes)
- def DoArpl(sreg,ads,os):
- #
- # if mode() == REAL or mode() == VM86 :
- # raise x86exception('fault', 6, -1,"Invalid instruction")
- # else:
- modrm_byte = fetch_code(1)
- reg_bits = (modrm_byte >> 3) &7
- source = regCode(reg_bits, 2)
- src_RPL = regFetch(source) & 3
- if modrm_byte >= 0xc0:
- rm_bits = modrm_byte & 7
- dest = regCode(rm_bits, 2)
- dst = regFetch(dest)
- else:
- (sreg, offset) = GetOffset(modrm_byte, ads, sreg)
- dst = lg_read(sreg, offset, 2)
- dst_RPL = dst & 3
- if src_RPL > dst_RPL:
- x = dst + src_RPL - dst_RPL
- if modrm_byte >= 0xc0:
- regStore(dest, x)
- else:
- lg_write(sreg, offset, x ,2)
- Flags["ZF"].setValue(1)
- else:
- Flags["ZF"].setValue(0)
- def DoBits(byte,sreg,ads,os,lock_flag):
- #
- # OpCodes 0F , Ay, y = 3,B and Bx where x = 3,A, or B
- #
- n_bytes = os >> 3
- imm_flag = (byte == 0xba)
- oper_num = (byte - 0x83) >> 3 # For non 0xba cases.
- modrm_byte = fetch_code(1)
- reg_bits = (modrm_byte >> 3) & 7
- rm_bits = modrm_byte & 7
- if modrm_byte >= 0xc and lock_flag:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- elif modrm_byte >= 0xc:
- dest = regCode(rm_bits, n_bytes)
- x = regFetch(dest)
- else:
- (sreg, offset) = GetOffset(modrm_byte,ads,sreg)
- x = lg_read(sreg, offset, n_bytes)
- if imm_flag:
- oper_num = reg_bits
- index = fetch_code(1)
- else:
- source = regCode(reg_bits, n_bytes)
- index = regFetch(source)
- # if modrm_byte >= 0xc:
- # pointer = offset + index / os
- # x = lg_read(sreg, pointer, n_bytes)
- index = index % os
- y = BitFlip(x,index,oper_num, n_bytes)
- if modrm_byte >= 0xc0:
- regStore(dest,y)
- else:
- lg_write(sreg,offset,y, n_bytes)
- def BitFlip(x, index, oper_num, n_bytes):
- n_bits = (n_bytes << 3)
- check_bit = (1 << index)
- Flags["CF"].setValue(int(x & check_bit != 0))
- if oper_num == 4: #Test
- pass
- elif oper_num == 5: #Set
- x = x | check_bit
- elif oper_num == 6: #Reset
- x = x & ~check_bit
- elif oper_num == 7: #Complement
- x = x ^ check_bit
- return x
- def DoBitScan(byte,sreg,ads,os,lock_flag):
- #
- # OpCodes 0F , BC or BD
- #
- n_bits = os
- n_bytes = os >> 3
- forward_flag = (byte == 0xbc)
- modrm_byte = fetch_code(1)
- reg_bits = (modrm_byte >> 3) & 7
- rm_bits = modrm_byte & 7
- dest = regCode(reg_bits, n_bytes)
- if modrm_byte >= 0xc and lock_flag:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- elif modrm_byte >= 0xc:
- src = rm_bits
- x = regFetch(src)
- else:
- (sreg, offset) = GetOffset(modrm_byte,ads,sreg)
- x = lg_read(sreg, offset, n_bytes)
- if forward_flag:
- i = 0
- mask = 1
- while mask & x == 0 and i < n_bits:
- mask = (mask << 1)
- i = i + 1
- if i == n_bits:
- Flags["ZF"].setValue(1)
- r = n_bits + 1 # Need to supply an undefined value
- else:
- Flags["ZF"].setValue(0)
- r = i
- else:
- i = n_bits -1
- mask = (1 << i)
- while mask & x == 0 and i >= 0:
- mask = (mask >> 1)
- i = i - 1
- if i == -1:
- r = n_bits + 1 # Need to supply an undefined value
- Flags["ZF"].setValue(1)
- else:
- Flags["ZF"].setValue(0)
- r = i
- y = r
- if Flags["ZF"].getValue() == 0:
- regStore(dest, y)
- def DoBound(sreg,ads,os):
- n_bytes = os >> 3
- modrm_byte = fetch_code(1)
- if modrm_byte >= 0xc0:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- reg_bits = (modrm_byte >> 3) & 7
- source = regCode(reg_bits, n_bytes)
- src1 = regFetch(source)
- (sreg, offset) = GetOffset(modrm_byte, ads, sreg)
- lower_bound = lg_read(sreg, offset, n_bytes)
- upper_bound = lg_read(sreg, offset + n_bytes, n_bytes)
- if src1 < lower_bound or src1 > upper_bound:
- raise x86exception('fault', 5, -1,"BOUND violation")
- def DoBswap(byte):
- reg_num = byte - 0xc8
- x = genReg[reg_num].getStringValue()
- regStore(reg_num, int(byte_swap(x),16))
- def DoCmpXchg(byte,sreg,ads,os):
- n_bytes = operand_size(os, byte & 1)
- modrm_byte = fetch_code(1)
- reg_bits = (modrm_byte >> 3) &7
- source = regCode(reg_bits, n_bytes)
- op2 = regFetch(source)
- if modrm_byte >= 0xc0:
- rm_bits = modrm_byte & 7
- dest = regCode(rm_bits, n_bytes)
- op1 = regFetch(dest)
- else:
- (sreg, offset) = GetOffset(modrm_byte, ads, sreg)
- op1 = lg_read(sreg, offset, n_bytes)
- acc = regCode(0,n_bytes)
- result = dif(op1, regFetch(acc))# Just for the flags
- if op1 == regFetch(acc): # Accumulator EAX, AX, or AL
- # Flags["ZF"].setValue(1)
- if modrm_byte >= 0xc0:
- regStore(dest,op2)
- else:
- lg_write(sreg,offset,op2,n_bytes)
- else:
- # Flags["ZF"].setValue(0)
- regStore(acc,op1)
- def DoCmpXchg8b(byte,sreg,ads,os):
- (sreg, offset) = GetOffset(modrm_byte, ads, sreg)
- dest_L = lg_read(sreg, offset, 4)
- dest_H = lg_read(sreg, offset + 4, 4)
- if dest_L == regFetch(0) and dest_H == regFetch(2): #dest=EDX:EAX
- Flags["ZF"].setValue(1)
- lg_write(sreg,offset, regFetch(3))
- lg_write(sreg,offset + 4,regFetch(1))
- else:
- Flags["ZF"].setValue(0)
- regStore(0,dest_L) #EAX
- regStore(2,dest_H) #EDX
- def DoCpuid():
- getEAX = regFetch(0)
- if getEAX == 0:
- regStore(0,1)
- regStore(3,0x65646957) #Wide
- regStore(2,0x2072656e) #ner
- regStore(1,0x53706d43) #CmpS
- else:
- raise x86exception('fault', 101, -1,"EAX > 0 not implemented")
- def DoCall(byte, os):
- n_bytes = os >> 3 # opcodes e8, 9a
- prog.call_depth = prog.call_depth + 1
- if byte == 0xe8:
- delta_EIP = fetch_code(-n_bytes)
- branch_EIP = EIP.getvalue() + delta_EIP
- # branch_EIP = branch_EIP & ((1 << n_bytes) -1)
- branch_EIP = branch_EIP & ((1 << os) -1)
- push(EIP.getvalue(), n_bytes)
- EIP.setvalue(branch_EIP)
- elif byte == 0x9a:
- NewOffset = fetch_code(n_bytes)
- NewSel = fetch_code(2)
- push(segReg[CS].get(), n_bytes)
- push(EIP.getvalue(), n_bytes)
- DoGoFar(NewSel, NewOffset, os, jump_not_call=False)
- def DoConv(byte, os):
- n_bytes = os >> 3
- if byte == 0x98:
- if archnum < 3:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- dest = regCode(0,n_bytes) #EAX or AX
- source = regCode(0 ,n_bytes >>1)
- x = regFetch(source)
- if n_bytes == 4:
- if x > 32767:
- x = x -65536 + 0x100000000
- elif n_bytes == 2:
- if x > 127:
- x = x - 256 + 65536
- else: # 0x99
- dest = regCode(2,n_bytes) #EDX or DX
- source = regCode(0,n_bytes)
- if n_bytes == 4:
- if regFetch(source) > 0x7ffffffff:
- x = 0xffffffff
- else:
- x = 0
- elif n_bytes == 2:
- if regFetch(source) > 32767:
- x = 65535
- else:
- x = 0
- regStore(dest, x)
- def DoEnter(os):
- frame_size = fetch_code(2)
- level = fetch_code(1) & 31
- n_bytes = os >> 3
- stackp = regCode(4, n_bytes) # ESP or SP
- basep = regCode(5, n_bytes) #EBP or BP
- push(regFetch(basep), n_bytes)
- framePtr = regFetch(stackp, n_bytes) # BP ok ??
- for i in range(1, level):
- regStore(basep, regFetch(basep) - n_bytes)
- offset = regFetch(basep)
- push(lg_read(SS, offset, n_bytes), n_bytes)
- push(framePtr, n_bytes)
- regStore(basep, framePtr)
- if descrVec[SS].DefaultAttr:
- stack_reg = 4 # ESP
- else:
- stack_reg = 12 # SP
- pointer = regFetch(stack_reg) - frame_size
- regStore(stack_reg,pointer)
- def DoFEFF(byte,sreg,ads,os,lock_flag):
- #
- # INC, DEC, CALL, JMP and PUSH
- #
- width_bit = byte & 1
- modrm_byte = fetch_code(1)
- op_num = (modrm_byte >> 3) & 7
- n_bytes = operand_size(os, width_bit)
- rm_bits = modrm_byte & 7
- if width_bit == 0 and op_num > 1:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- elif op_num < 2:
- save_CF = Flags["CF"].getValue()
- if modrm_byte >= 0xc0 and lock_flag:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- elif modrm_byte >= 0xc0:
- dest = regCode(rm_bits,n_bytes)
- if op_num == 0:
- regStore(dest, sum(regFetch(dest),1,n_bytes<< 3))
- elif op_num == 1:
- regStore(dest, dif(regFetch(dest),1,n_bytes<< 3))
- else:
- (sreg, offset) = GetOffset(modrm_byte,ads,sreg)
- mem_num = lg_read(sreg, offset, n_bytes)
- if op_num == 0:
- mem_num = sum(mem_num, 1, n_bytes << 3)
- elif op_num == 1:
- mem_num = dif(mem_num, 1, n_bytes << 3)
- lg_write(sreg, offset, mem_num, n_bytes)
- Flags["CF"].setValue(save_CF)
- elif lock_flag:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- elif op_num == 2 or op_num == 4: # Near Call or Jump r/m
- if modrm_byte >= 0xc0:
- source = regCode(rm_bits,n_bytes)
- branch_EIP = regFetch(source)
- else:
- (sreg, offset) = GetOffset(modrm_byte,ads,sreg)
- branch_EIP = lg_read(sreg, offset, n_bytes)
- if os == 16: branch_EIP &= 65535
- if op_num == 2:
- push(EIP.getvalue(), n_bytes)
- prog.call_depth = proc.call_depth + 1
- EIP.setvalue(branch_EIP)
- elif op_num == 3 or op_num == 5: # Far Call or Jump r/m
- if modrm_byte >= 0xc0:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- else:
- (sreg, offset) = GetOffset(modrm_byte,ads,sreg)
- new_offset = lg_read(sreg, offset, n_bytes)
- new_sel = lg_read(sreg, offset + n_bytes, 2)
- if op_num == 3:
- prog.call_depth = prog.call_depth + 1
- push(segReg[CS].get(), n_bytes)
- push(EIP.getvalue(), n_bytes)
- jmp_not_call = False
- else:
- jmp_not_call = True
- DoGoFar(new_sel,new_offset, os, jmp_not_call)
- elif op_num == 6: # Push rmv
- if modrm_byte >= 0xc0:
- source = regCode(rm_bits, n_bytes)
- x = regFetch(source)
- else:
- (sreg, offset) = GetOffset(modrm_byte,ads,sreg)
- x = lg_read(sreg, offset, n_bytes)
- push(x, n_bytes)
- else:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- def DoImul3(byte,sreg,ads,os):
- n_bytes = operand_size(os, 1)
- if byte == 0x69:
- imm_width_bit = 1
- elif byte == 0x6b:
- imm_width_bit = 0
- elif byte == 0xaf:
- imm_width_bit = None
- byte = fetch_code(1)
- reg_bits = (byte >> 3) & 7
- rm_bits = byte & 7
- dest = regCode(reg_bits, n_bytes)
- if imm_width_bit == None:
- op1_num = regFetch(dest)
- else:
- n_imm_bytes = operand_size(os, imm_width_bit)
- op1_num = fetch_code(-n_imm_bytes)
- # print(n_imm_bytes, op1_num)
- if byte >= 0xc0:
- source = regCode(rm_bits, n_bytes)
- op2_num = regFetch(source)
- else:
- sreg,offset = GetOffset(byte,ads,sreg)
- op2_num = lg_read(sreg,offset,n_bytes)
- y, x = signed_prod(op1_num, op2_num, n_bytes)
- regStore(dest,x)
- def DoIncDec(byte,os=32):
- """ Increment Decrement Function for opcodes (4x)"""
- n_bytes= os >> 3
- dest = regCode(byte&7,n_bytes)
- save_CF = Flags["CF"].getValue()
- if byte > 0x47:
- x = dif(regFetch(dest),1,os)
- else:
- x = sum(regFetch(dest),1,os)
- regStore(dest,x)
- Flags["CF"].setValue(save_CF)
- def DoInOut(byte,ads, os):
- n_bytes = operand_size(os,byte&1)
- n_address_bytes = ads >> 3
- if byte&3 < 2:
- signal.input_register = regCode(0,n_bytes)
- if byte == 0xe4 or byte == 0xe5:
- port_num = fetch_code(1)
- elif byte == 0xec or byte == 0xed:
- port_num = regFetch(10) #DX
- else:
- port_num = regFetch(10) #DX
- pointer_reg = regCode(7, n_address_bytes)
- if n_bytes == 4:
- signal.input_register = pointer_reg
- elif n_bytes == 2:
- signal.input_register = pointer_reg & 14
- elif n_bytes == 1:
- signal.input_register = pointer_reg & 13
- if port_num != 0:
- raise x86exception('fault', 102, -1,"Edlinas input port is 0")
- prog.set_execstate('blocked')
- else:
- source = regCode(0,n_bytes)
- num = regFetch(source)
- if byte == 0xe6 or byte == 0xe7:
- port_num = fetch_code(1)
- elif byte == 0xee or byte == 0xef:
- port_num = regFetch(10) #DX
- else:
- port_num = regFetch(10) #DX
- pointer_reg = regCode(6, n_address_bytes)
- num = lg_read(ES, regFetch(pointer_reg), n_bytes)
- if Flags["DF"].getValue() == 0:
- regStore(pointer_reg, regFetch(pointer_reg) + n_bytes)
- else:
- regStore(pointer_reg, regFetch(pointer_reg) - n_bytes)
- if signal.pending_repeat:
- handle_repeat(n_address_bytes)
- if port_num != 1:
- raise x86exception('fault', 103, -1,"Edlinas output port is 1")
- print_feedback( "OUTPUT: " + str(num) + " ")
- print_output(str(num))
- def DoInt():
- interrupt_number = fetch_code(1)
- raise x86exception('fault', interrupt_number, -1,
- "Software interrupt number: " + str(interrupt_number))
- def DoInto():
- if Flags["OF"].getValue():
- raise x86exception('fault', 4, -1, "Integer overflow")
- def DoJcond(byte,os):
- #
- # Handle 7x short jumps and 0F 8x long jumps
- #
- n_bytes = operand_size(os, (byte >> 4) - 7)
- jump_num = byte & 15
- delta_EIP = fetch_code(-n_bytes)
- # print_feedback( "delta_EIP = " + str(delta_EIP))
- branch_EIP = EIP.getvalue() + delta_EIP
- assert branch_EIP >= 0
- if jump_num == 0 and Flags["OF"].getValue() == 1:
- EIP.setvalue(branch_EIP)
- elif jump_num == 1 and Flags["OF"].getValue() == 0:
- EIP.setvalue(branch_EIP)
- elif jump_num == 2 and Flags["CF"].getValue() == 1:
- EIP.setvalue(branch_EIP)
- elif jump_num == 3 and Flags["CF"].getValue() == 0:
- EIP.setvalue(branch_EIP)
- elif jump_num == 4 and Flags["ZF"].getValue() == 1:
- EIP.setvalue(branch_EIP)
- elif jump_num == 5 and Flags["ZF"].getValue() == 0:
- EIP.setvalue(branch_EIP)
- elif jump_num == 6 and Flags["CF"].getValue()| Flags["ZF"].getValue() == 1:
- EIP.setvalue(branch_EIP)
- elif jump_num == 7 and Flags["CF"].getValue()| Flags["ZF"].getValue() == 0:
- EIP.setvalue(branch_EIP)
- elif jump_num == 8 and Flags["SF"].getValue() == 1:
- EIP.setvalue(branch_EIP)
- elif jump_num == 9 and Flags["SF"].getValue() == 0:
- EIP.setvalue(branch_EIP)
- elif jump_num == 10 and Flags["PF"].getValue() == 1:
- EIP.setvalue(branch_EIP)
- elif jump_num == 11 and Flags["PF"].getValue() == 0:
- EIP.setvalue(branch_EIP)
- elif jump_num == 12 and Flags["SF"].getValue() != Flags["OF"].getValue():
- EIP.setvalue(branch_EIP)
- elif jump_num == 13 and Flags["SF"].getValue() == Flags["OF"].getValue():
- EIP.setvalue(branch_EIP)
- elif jump_num == 14:
- if Flags["SF"].getValue()!= Flags["OF"].getValue()or Flags["ZF"].getValue() == 1:
- EIP.setvalue(branch_EIP)
- elif jump_num == 15:
- if Flags["SF"].getValue()== Flags["OF"].getValue() and Flags["ZF"].getValue() == 0:
- EIP.setvalue(branch_EIP)
- def DoJmp(byte, os):
- n_bytes = operand_size(os, 0xeb - byte)
- if byte == 0xe9 or byte == 0xeb:
- delta_EIP = fetch_code(-n_bytes)
- branch_EIP = EIP.getvalue() + delta_EIP
- if branch_EIP > 0xffffffff:
- branch_EIP = branch_EIP & 0xffffffff
- EIP.setvalue(branch_EIP)
- elif byte == 0xea:
- offset = fetch_code(n_bytes)
- sel = fetch_code(2)
- DoGoFar(sel, offset, os, True)
- def DoGoFar(new_sel,new_offset, os, jmp_not_call):
- raise x86exception('fault', 101, -1,"Instruction not implemented")
- def DoLahf():
- ah = getFlags(2) #SF,ZF,AF,PF,CF
- regStore(20, ah)
- def DoLea(sreg,ads,os):
- n_bytes = os >> 3
- modrm_byte = fetch_code(1)
- reg_bits = (modrm_byte >> 3)&7
- dest = regCode(reg_bits,n_bytes)
- (sreg, offset) = GetOffset(modrm_byte,ads,sreg)
- regStore(dest, offset)
- def DoLeave(os):
- if descrVec[SS].DefaultAttr == 1:
- stack_reg = 4 #ESP
- basep_reg = 5 #EBP
- else:
- stack_reg = 12 #SP
- basep_reg = 13 #BP
- regStore(stack_reg,regFetch(basep_reg))
- n_bytes = os >> 3
- regStore(regCode(5, n_bytes), pop(n_bytes))
- def DoLodSeg(byte, os):
- if byte == 0xc5: # LDS
- segreg = DS
- elif byte == 0xc4: # LES
- segreg = ES
- elif byte == 0xb4: # LFS
- segreg = FS
- elif byte == 0xb5: # LGS
- segreg = GS
- n_bytes = os >> 3
- modrm_byte = fetch_code(1)
- reg_bits = (modrm_byte >> 3)&7
- dst = regCode(reg_bits,n_bytes)
- (sreg, offset) = GetOffset(modrm_byte,ads,sreg)
- off = lg_read(sreg,offset,n_bytes)
- sel = lg_read(sreg,offset + n_bytes, n_bytes)
- if mode() == REAL or mode() == VM86:
- descrVec[segreg].Base.setValue(sel << 4)
- else:
- load_data_seg(sel, descrVec[segreg], False)
- regStore(dst, off)
- regStore(segreg, sel)
- def DoLoop(byte,ads, os):
- counter = regCode(1, ads >> 3)
- jump = fetch_code(1)
- if jump > 127:
- jump = jump - 256
- old_EIP = EIP.getvalue()
- branch_EIP = EIP.getvalue() + jump
- if branch_EIP < 0:
- branch_EIP = branch_EIP + (1 << os)
- elif branch_EIP >= 1 << os:
- branch_EIP = branch_EIP & ((1 << os)-1)
- if os == 16:
- branch_EIP = (old_EIP & 0xffff0000)| (branch_EIP & 65535)
- if byte < 0xe4:
- regStore(counter,regFetch(counter) - 1)
- if byte == 0xe0 and Flags["ZF"].getValue() == 0 and regFetch(counter) != 0:
- EIP.setvalue(branch_EIP)
- elif byte == 0xe1 and Flags["ZF"].getValue() == 1 and regFetch(counter) != 0:
- EIP.setvalue(branch_EIP)
- elif byte == 0xe2 and regFetch(counter) != 0:
- EIP.setvalue(branch_EIP)
- elif byte == 0xe3 and regFetch(counter) == 0:
- EIP.setvalue(branch_EIP)
- def DoMov(byte,sgreg,ads,os): # MOV for opcodes 8x, 7 < x < C
- n_bytes = operand_size(os,byte&1)
- r_isdest = (byte > 0x89)
- modrm_byte = fetch_code(1)
- reg_bits = (modrm_byte >> 3)&7
- rm_bits = modrm_byte & 7
- if r_isdest :
- dest = regCode(reg_bits,n_bytes)
- else:
- source = regCode(reg_bits,n_bytes)
- reg_val = regFetch(source)
- if modrm_byte >= 0xc0:
- m_reg = regCode(rm_bits,n_bytes)
- if r_isdest:
- x = regFetch(m_reg)
- regStore(dest,x)
- else:
- regStore(m_reg,reg_val)
- else:
- (sreg, offset) = GetOffset(modrm_byte,ads,sgreg)
- # print "sreg = ", sreg, "offset = ", offset
- if r_isdest:
- x = lg_read(sreg,offset,n_bytes)
- regStore(dest,x)
- else:
- lg_write(sreg,offset, reg_val,n_bytes)
- def DoMovaI(byte,sreg, os): # MOV for opcodes Ax, x < 4
- n_bytes = operand_size(os,byte&1)
- a_reg = regCode(0,n_bytes)
- offset = fetch_code(n_bytes)
- if byte < 0xa2:
- x = lg_read(sreg,offset,n_bytes)
- regStore(a_reg, x)
- else:
- x = regFetch(a_reg)
- lg_write(sreg,offset, x,n_bytes)
- def DoMovmI(byte, ads, os): #MOV for opcodes C6, C7
- n_bytes = operand_size(os,(byte>>3)&1)
- modrm_byte = fetch_code(1)
- reg_bits = (modrm_byte >> 3) & 7
- rm_bits = modrm_byte & 7
- if reg_bits > 0:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- (sreg, offset) = GetOffset(modrm_byte,ads)
- imm = fetch_code(n_bytes)
- if modrm_byte >= 0xc0:
- m_reg = regCode(rm_bits,n_bytes)
- regStore(m_reg,imm)
- else:
- lg_write(sreg,offset, imm, n_bytes)
- def DoMovrI(byte,os): # MOV for opcodes Bx
- n_bytes = operand_size(os,(byte>>3)&1)
- dest = regCode(byte&7,n_bytes)
- imm = fetch_code(n_bytes)
- regStore(dest,imm)
- def DoMovs(byte,sreg,ads,os): #Mov for opcodes 8C, 8E
- modrm_byte = fetch_code(1)
- reg_bits = (modrm_byte >> 3) & 7
- rm_bits = modrm_byte & 7
- segreg = regCode(reg_bits, 5)
- if byte == 0x8e: # Mov segreg, rm
- desc = descrVec[reg_bits]
- if modrm_byte >= 0xc0:
- source = regCode(rm_bits, 2)
- sel = regFetch(source)
- else:
- sreg, offset = GetOffset(modrm_byte,ads,sreg)
- sel = lg_read(sreg,offset,2)
- if mode() == PROTECTED:
- if segreg == SS:
- load_SS(sel, desc, False)
- else:
- load_data_seg(sel, desc, False)
- else:
- desc.Valid.setValue(True)
- desc.Base.setValue(sel << 4)
- desc.Limit.setValue(0xFFFF)
- desc.DefaultAttr.setValue(False)
- desc.Readable.setValue(True)
- desc.Writable.setValue(True)
- desc.ExpandDown.setValue(False)
- desc.Executable.setValue(False)
- regStore(segreg, sel)
- elif byte == 0x8c: # Mov rm, segreg
- x = regFetch(segreg)
- if modrm_byte >= 0xc0:
- dest = regCode(rm_bits,2)
- regStore(dest,x)
- else:
- sreg, offset = GetOffset(modrm_byte,ads,sreg)
- lg_write(sreg, offset, x, 2)
- def DoMovt(byte2):
- modrm_byte = fetch_code(1)
- reg_bits = (modrm_byte >> 3) & 7
- rm_bits = modrm_byte & 7
- if byte2 == 0x20 or byte2 == 0x21 or byte2 == 0x24: # Store
- # destination = genReg[rm_bits]
- dest = rm_bits
- source = reg_bits
- if byte2 == 0x20: # CR
- source = source + 48
- elif byte2 == 0x21: # DR
- source = source + 32
- elif byte2 == 0x24: # TR
- source = source + 40
- elif byte2 == 0x22 or byte2 == 0x23 or byte2 == 0x26: # Load
- # source = genReg[rm_bits]
- source = rm_bits
- dest = reg_bits
- if byte2 == 0x22: # CR
- dest = dest + 48
- elif byte2 == 0x23: # DR
- dest = dest + 32
- elif byte2 == 0x26: # TR
- dest = dest + 40
- else:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- x = regFetch(source)
- regStore(dest,x)
- def DoMovx(hb2,sreg,ads,os):
- source_width_bit = hb2 & 1
- dest_signext_bit = (hb2 >> 3) & 1
- n_dest_bytes = os >> 3
- if source_width_bit == 0:
- n_source_bytes = 1
- else:
- n_source_bytes = n_dest_bytes >> 1
- modrm_byte = fetch_code(1)
- reg_bits = (modrm_byte >> 3) & 7
- dest = regCode(reg_bits, n_dest_bytes)
- if modrm_byte >= 0xc:
- rm_bits = modrm_byte & 7
- source_reg = regCode(rm_bits,n_source_bytes)
- x = regFetch(source_reg)
- else:
- (sreg, offset) = GetOffset(modrm_byte,ads,sreg)
- x = lg_read(sreg,offset,n_source_bytes)
- if dest_signext_bit:
- if n_source_bytes == 1:
- if x > 127:
- if n_dest_bytes == 2:
- x = (x - 256) + 65536
- elif n_dest_bytes == 4:
- x = (x - 256) + 0x100000000
- elif n_source_bytes == 2:
- #n_dest_bytes == 4
- if x > 65535:
- x = (x - 65536) + 0x100000000
- regStore(dest, x)
- def DoPop(byte,sreg,ads,os):
- n_bytes = (os>>3) # opcodes 5y, y > 7, 8f , 0F A1,A9
- val = pop(n_bytes)
- if byte > 0x57 and byte < 0x60:
- reg_num = regCode(byte & 7, n_bytes)
- regStore(reg_num, val)
- return
- if byte == 0x8f:
- modrm_byte = fetch_code(1)
- reg_bits = (modrm_byte >> 3)&7
- if reg_bits != 0:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- if modrm_byte >= 0xc0:
- mem_bits = modrm_byte &7
- dest = regCode(mem_bits, n_bytes)
- regStore(dest,val)
- else:
- (sreg, offset) = GetOffset(modrm_byte,ads,sreg)
- lg_write(sreg,offset,val,n_bytes)
- return
- if byte < 0x20 and byte&7 == 7:
- seg_reg = byte >> 3
- segReg[seg_reg].set(val)
- elif byte in [0xa1, 0xa9]: # 0F byte already discarded
- seg_reg = ((byte -0xa1)>> 3) + 4
- segReg[seg_reg].set(val)
- else:
- raise x86exception('fault', 101, -1,"Instruction not implemented")
- # elif byte < 0x20 and byte & 7 == 6:
- # src = segReg[byte>>3].get()
- # else:
- # src = segReg[((byte - 0xa0)>>3) + 4].get()
- def Popf(os):
- n_bytes = os >> 3
- if n_bytes == 4:
- eflg = pop(os) & 0x277fd7
- setFlags(eflg,4)
- else:
- eflg = pop(os)
- setFlags(eflg,2)
- def DoPusha(os):
- n_bytes = os >> 3
- sp_reg = regCode( 4, n_bytes) # ESP or SP
- stack_pointer = regFetch(sp_reg)
- push(regCode(0 ,n_bytes), n_bytes)
- push(regCode(1 ,n_bytes), n_bytes)
- push(regCode(2 ,n_bytes), n_bytes)
- push(regCode(3 ,n_bytes), n_bytes)
- push(stack_pointer, n_bytes)
- push(regCode(5 ,n_bytes), n_bytes)
- push(regCode(6 ,n_bytes), n_bytes)
- push(regCode(7 ,n_bytes), n_bytes)
- def Popa(os):
- n_bytes = os >> 3
- regStore(regCode(7 ,n_bytes), pop(n_bytes))
- regStore(regCode(6 ,n_bytes), pop(n_bytes))
- regStore(regCode(5 ,n_bytes), pop(n_bytes))
- pop(n_bytes)
- regStore(regCode(3 ,n_bytes), pop(n_bytes))
- regStore(regCode(2 ,n_bytes), pop(n_bytes))
- regStore(regCode(1 ,n_bytes), pop(n_bytes))
- regStore(regCode(0 ,n_bytes), pop(n_bytes))
- def DoPush(byte,os):
- if byte > 0x20 and byte < 0x58:
- reg_num = regCode( byte & 7, os >> 3)
- src = regFetch(reg_num)
- elif byte == 0x6a:
- src = fetch_code(1)
- if src > 127:
- src = src - 256 + (1 << os)
- elif byte == 0x68:
- src = fetch_code(os>>3)
- elif byte < 0x20 and byte & 7 == 6:
- src = segReg[byte>>3].get()
- elif byte in [0xa0, 0xa8]: # 0F byte already discarded
- src = segReg[((byte - 0xa0)>>3) + 4].get()
- else:
- raise x86exception('fault', 101, -1,"Instruction not implemented")
- push(src,os>>3)
- def Pushf(os):
- eflg = getFlags(4)
- eflg = eflg & 0xfcffff #Clear VM and RF bits
- if os == 32:
- push(eflg, 4)
- else:
- push(eflg & 0xffff, 2)
- def DoRet(byte, os): # opcodes c2, c3, ca, cb
- # prog.call_depth = prog.call_depth - 1
- n_bytes = os >> 3
- EIP.setvalue(pop(n_bytes))
- if byte == 0xca or byte == 0xcb:
- segReg[CS].set(pop(n_bytes) & 0xffff)
- if byte == 0xc2 or byte == 0xca:
- n_popbytes = fetch_code(2)
- else:
- n_popbytes = 0
- if descrVec[CS].DefaultAttr:
- stack_reg = 4 # ESP
- else:
- stack_reg = 12 # SP
- regStore(stack_reg, regFetch(stack_reg) + n_popbytes)
- if byte == 0xc2 or byte == 0xc3:
- return
- #
- # Far return is not done!
- #
- #
- def DoSahf():
- ah = regFetch(20)
- Flags["SF"].setValue(int(ah & 128!=0))
- Flags["ZF"].setValue(int(ah & 64!=0))
- Flags["AF"].setValue(int(ah & 16!=0))
- Flags["PF"].setValue(int(ah & 4!=0))
- Flags["CF"].setValue(int(ah & 2!=0))
- def Setcond(hb2, sreg,ads):
- val = 0
- if hb2 == 0 and Flags["OF"].getValue() == 1:
- val = 1
- elif hb2 == 1 and Flags["OF"].getValue() == 0:
- val = 1
- elif hb2 == 2 and Flags["CF"].getValue() == 1:
- val = 1
- elif hb2 == 3 and Flags["CF"].getValue() == 0:
- val = 1
- elif hb2 == 4 and Flags["ZF"].getValue() == 1:
- val = 1
- elif hb2 == 5 and Flags["ZF"].getValue() == 0:
- val = 1
- elif hb2 == 6 and Flags["CF"].getValue()| Flags["ZF"].getValue() == 1:
- val = 1
- elif hb2 == 7 and Flags["CF"].getValue()| Flags["ZF"].getValue() == 0:
- val = 1
- elif hb2 == 8 and Flags["SF"].getValue() == 1:
- val = 1
- elif hb2 == 9 and Flags["SF"].getValue() == 0:
- val = 1
- elif hb2 == 10 and Flags["PF"].getValue() == 1:
- val = 1
- elif hb2 == 11 and Flags["PF"].getValue() == 0:
- val = 1
- elif hb2 == 12 and Flags["SF"].getValue()!= Flags["OF"].getValue():
- val = 1
- elif hb2 == 13 and Flags["SF"].getValue()== Flags["OF"].getValue():
- val = 1
- elif hb2 == 14:
- if Flags["SF"].getValue()!= Flags["OF"].getValue() or Flags["ZF"].getValue() == 1:
- val = 1
- elif hb2 == 15:
- if Flags["SF"].getValue()== Flags["OF"].getValue() and Flags["ZF"].getValue() == 0:
- val = 1
- modrm_byte = fetch_code(1)
- rm_bits = modrm_byte & 7
- reg_num = regCode(rm_bits, 1) # 1 byte register
- if modrm_byte >= 0xc0:
- regStore(reg_num, val)
- else:
- (sreg, offset) = GetOffset(modrm_byte,ads,sreg)
- lg_write(sreg, offset, val, 1)
- def DoShift(byte,sreg,ads,os):
- #
- # Funnel shift Opcodes 0F Ax, x = 4,5,C & D
- #
- # First byte opcodes C0, C1, Dx x < 4
- #
- double_flag = (byte < 0xb0)
- if double_flag:
- imm_flag = (byte & 1 == 0)
- width_bit = 1
- left_flag = (byte & 8 == 0)
- else:
- imm_flag = (byte < 0xd0)
- width_bit = (byte & 1)
- n_bytes = operand_size(os, width_bit)
- bit_len = (n_bytes << 3)
- if not imm_flag:
- if double_flag or (byte & 2 == 2):
- num_shifts = regFetch(17) #CL
- else:
- num_shifts = 1
- byte = fetch_code(1)
- reg_bits = (byte >> 3) & 7
- rm_bits = byte & 7
- if double_flag:
- source = reg_bits
- pad = regFetch(source)
- y = ('{0:0' + str(bit_len)+ 'b}').format(pad)[0:bit_len]
- if left_flag:
- op_num = -1
- else:
- op_num = -2
- else:
- op_num = reg_bits
- if byte >= 0xc0:
- dest = rm_bits
- dest = regCode(dest,n_bytes)
- x = ('{0:0' + str(bit_len)+ 'b}').format(regFetch(dest))[0:bit_len]
- else:
- sreg,offset = GetOffset(byte,ads,seg_reg = sreg)
- imm_num = lg_read(sreg,offset,n_bytes)
- x = ('{0:0' + str(bit_len)+ 'b}').format(imm_num)[0:bit_len]
- if imm_flag:
- num_shifts = fetch_code(1)
- if num_shifts == 0:
- return
- if op_num == 0: # ROL
- x = x[num_shifts:] + x[:num_shifts]
- Flags["CF"].setValue(int(x[-1]))
- if num_shifts == 1: #Set if CF does not match most sig bit
- Flags["OF"].setValue(int(not(Flags["CF"].getValue() == int(x[0])))) #Agarwal p 548
- else:
- Flags["OF"].setValue(random.randint(0,1))
- elif op_num == 1: # ROR
- x = x[bit_len - num_shifts:] + x[:bit_len - num_shifts]
- Flags["CF"].setValue(int(x[0]))
- if num_shifts == 1: # Set if two most sig bits differ
- Flags["OF"].setValue(int(not(x[0] == x[1]))) #Agarwal p 548
- else:
- Flags["OF"].setValue(random.randint(0,1))
- elif op_num == 2: # RCL
- x = str(Flags["CF"].getValue()) + x
- x = x[num_shifts:] + x[:num_shifts]
- Flags["CF"].setValue(int(x[0]))
- x = x[1:]
- if num_shifts == 1: #Set if CF does not match most sig bit
- Flags["OF"].setValue(int(not(Flags["CF"].getValue() == int(x[0])))) #Agarwal p 548
- else:
- Flags["OF"].setValue(random.randint(0,1))
- elif op_num == 3: # RCR
- x = str(Flags["CF"].getValue()) + x
- x = x[bit_len + 1- num_shifts:] + x[:bit_len + 1- num_shifts]
- Flags["CF"].setValue(int(x[0]))
- x = x[1:]
- if num_shifts == 1: # Set if two most sig bits differ
- Flags["OF"].setValue(int(not(x[0] == x[1]))) #Agarwal p 548
- else:
- Flags["OF"].setValue(random.randint(0,1))
- elif op_num == 4: # SHL
- Flags["CF"].setValue(int(x[num_shifts -1]))
- x = x[num_shifts:] + ''.zfill(num_shifts)
- if num_shifts == 1: #Set if CF does not match most sig bit
- Flags["OF"].setValue(int(not(Flags["CF"].getValue() == int(x[0])))) #Agarwal p 548
- else:
- Flags["OF"].setValue(random.randint(0,1))
- Flags["ZF"].setValue(int('1' not in x))
- Flags["SF"].setValue(int(x[0]))
- elif op_num == 5: # SHR
- Flags["CF"].setValue(int(x[-num_shifts]))
- if num_shifts == 1: #Agarwal p 563
- Flags["OF"].setValue(int(x[0]))
- else:
- Flags["OF"].setValue(random.randint(0,1))
- x = ''.zfill(num_shifts) + x[:-num_shifts]
- Flags["ZF"].setValue(int('1' not in x))
- Flags["SF"].setValue(int(x[0]))
- elif op_num == 6:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- elif op_num == 7: # SAR
- Flags["CF"].setValue(int(x[-num_shifts]))
- if num_shifts == 1:
- Flags["OF"].setValue(0)
- x = ''.join([x[0] for t in range(num_shifts)]) + x[:-num_shifts]
- Flags["ZF"].setValue(int('1' not in x))
- Flags["SF"].setValue(int(x[0]))
- elif op_num == -1: # SHLD p 563
- num_shifts = num_shifts % os
- Flags["CF"].setValue(int(x[num_shifts]))
- y = y[:num_shifts]
- x = x[num_shifts:] + y
- Flags["OF"].setValue(int(not(Flags["CF"].getValue() == int(x[0])))) #Agarwal p 548
- Flags["ZF"].setValue(int('1' not in x))
- Flags["SF"].setValue(int(x[0]))
- Flags["PF"].setValue(evenParity(int(x,2)))
- elif op_num == -2: # SHRD p 565
- num_shifts = num_shifts % os
- Flags["CF"].setValue(int(x[-num_shifts]))
- y = y[-num_shifts:]
- x = y + x[:-num_shifts]
- Flags["OF"].setValue(int(not(x[0] == x[1])))
- Flags["ZF"].setValue(int('1' not in x))
- Flags["SF"].setValue(int(x[0]))
- Flags["PF"].setValue(evenParity(int(x,2)))
- if byte >= 0xc0:
- regStore(dest,int(x,2))
- else:
- lg_write(sreg,offset,int(x,2),n_bytes)
- def DoString(byte, ads, os):
- n_bytes = operand_size(os, byte &1)
- n_adbytes = ads >> 3
- if byte < 0x70:
- DoInOut(byte, ads, os)
- # if byte < 0x6e: #INS
- # pass
- # else: #OUTS
- # pass
- else:
- hb2by2 = (byte & 15) >> 1
- if hb2by2 == 2: #MOVS
- source = regCode(6, n_adbytes) # ESI
- dest = regCode(7, n_adbytes) #EDI
- x = lg_read(DS, regFetch(source), n_bytes)
- lg_write(ES, regFetch(dest), x, n_bytes)
- if Flags["DF"].getValue() == 1:
- regStore(source,regFetch(source) - n_bytes)
- regStore(dest,regFetch(dest) - n_bytes)
- else:
- regStore(source,regFetch(source) + n_bytes)
- regStore(dest,regFetch(dest) + n_bytes)
- elif hb2by2 == 3:#CMPS
- source = regCode(6, n_adbytes) # ESI
- dest = regCode(7, n_adbytes) #EDI
- x = lg_read(DS, regFetch(source), n_bytes)
- y = lg_read(ES, regFetch(dest), n_bytes)
- z = dif(x,y,n_bytes<<3)
- if Flags["DF"].getValue() == 1:
- regStore(source,regFetch(source) - n_bytes)
- regStore(dest,regFetch(dest) - n_bytes)
- else:
- regStore(source,regFetch(source) + n_bytes)
- regStore(dest,regFetch(dest) + n_bytes)
- elif hb2by2 == 5:#STOS
- source = regCode(0, n_bytes) # EAX
- dest = regCode(7, n_adbytes) #EDI
- lg_write(ES, regFetch(dest), regFetch(source), n_bytes)
- if Flags["DF"].getValue() == 1:
- regStore(dest,regFetch(dest) - n_bytes)
- else:
- regStore(dest,regFetch(dest) + n_bytes)
- elif hb2by2 == 6: # LODS
- source = regCode(7, n_adbytes) # EDI
- dest = regCode(0, n_bytes) #EAX
- x = lg_read(DS,regFetch(source), n_bytes)
- regStore(dest, x)
- if Flags["DF"].getValue() == 1:
- regStore(dest,regFetch(source) - n_bytes)
- else:
- regStore(dest,regFetch(source) + n_bytes)
- elif hb2by2 == 7:#SCAS
- source = regCode(0, n_bytes) # EAX
- dest = regCode(7, n_adbytes) #EDI
- x = regFetch(source)
- y = lg_read(ES, regFetch(dest), n_bytes)
- z = dif(x,y,n_bytes<<3)
- if Flags["DF"].getValue() == 1:
- regStore(dest,regFetch(dest) - n_bytes)
- else:
- regStore(dest,regFetch(dest) + n_bytes)
- if signal.pending_repeat:
- handle_repeat(n_adbytes)
- def DoTest(byte,sreg,ads,os):
- n_bytes = operand_size(os, byte&1)
- if byte < 0xa0:
- byte = fetch_code(1)
- reg_bits = (byte >> 3) & 7
- rm_bits = byte & 7
- dest = regCode(reg_bits, n_bytes)
- if byte >= 0xc0:
- source = rm_bits
- bblog(regFetch(dest),regFetch(source), 4, n_bytes)
- else:
- sgreg, offset = GetOffset(byte,ads,seg_reg=sreg)
- imm_num = lg_read(sgreg,offset,n_bytes)
- bblog(regFetch(dest), imm_num, 4, n_bytes)
- else:
- dest = regCode(0, n_bytes) #EAX = 0
- imm_num = fetch_code(n_bytes)
- bblog(regFetch(dest), imm_num, 4, n_bytes)
- def DoUnM(byte,sreg,ads,os,lock_flag = 0):
- #
- # Unary Operations, opcodes F6 and F7
- #
- # /r, 0:TEST imm, 2:NOT, 3:NEG, 4:MUL, 5:IMUL, 6:DIV, 7:IDIV
- #
- n_bytes = operand_size(os, byte & 1)
- byte = fetch_code(1)
- reg_bits = (byte >> 3) & 7
- rm_bits = byte & 7
- if reg_bits == 1:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- if byte >= 0xc0 and lock_flag:
- raise x86exception('fault', 6, -1,"Lock Invalid")
- elif byte >= 0xc0:
- dest = regCode(rm_bits ,n_bytes)
- mem_num = regFetch(dest)
- else:
- sreg, offset = GetOffset(byte, ads, sreg)
- mem_num = lg_read(sreg, offset, n_bytes)
- if reg_bits == 0:
- imm_num = fetch_code(n_bytes)
- bblog(mem_num, imm_num, 4, n_bytes)
- elif reg_bits == 2:
- mem_num = (1 << (n_bytes << 3))- 1 - mem_num
- elif reg_bits == 3:
- mem_num = dif(0, mem_num, n_bytes<< 3)
- else:
- # accum = regCode(0,n_bytes)
- # x = regFetch(accum)
- if n_bytes == 1:
- if reg_bits > 5:
- y = regFetch(20) # AH
- x = regFetch(8) # AX
- else:
- x = regFetch(16) # AL
- elif n_bytes == 2:
- if reg_bits > 5:
- y = regFetch(10) # DX
- x = (y << 16) + regFetch(8)# DX:AX
- else:
- x = regFetch(8) # AX
- elif n_bytes == 4:
- if reg_bits > 5:
- y = regFetch(2) # EDX
- x = (y << 32) + regFetch(0)# EDX:EAX
- else:
- x = regFetch(0)
- # print("1:x = ", x)
- # print("reg_bits =", reg_bits)
- if reg_bits == 4:
- # print("mem_num = ", mem_num)
- # print("n_bytes = ", n_bytes)
- y,x = prod(x, mem_num, n_bytes)
- elif reg_bits == 5:
- y,x = signed_prod(x, mem_num, n_bytes)
- elif reg_bits == 6:
- y,x = divide(x,mem_num, n_bytes)
- elif reg_bits == 7:
- y,x = signed_divide(x,mem_num, n_bytes)
- # print("2:x = ", x)
- if n_bytes == 1:
- regStore(16, x) # AL
- regStore(20, y) # AH
- elif n_bytes == 2:
- regStore( 8, x) # AX
- regStore(10, y) # DX
- elif n_bytes == 4:
- regStore(0, x) # EAX
- regStore(2, y) # EDX
- if reg_bits == 2 or reg_bits == 3:
- if byte >= 0xc0:
- regStore(dest, mem_num)
- else:
- lg_write(sreg, offset, mem_num, n_bytes)
- def DoXadd(byte,sreg,ads,os):
- n_bytes = operand_size(os, byte & 1)
- modrm_byte = fetch_code(1)
- reg_bits = (modrm_byte >> 3)&7
- rm_bits = modrm_byte & 7
- source = regCode(reg_bits, n_bytes)
- op2 = regFetch(source)
- temp = op2
- if modrm_byte >= 0xc0:
- dest = regCode(rm_bits, n_bytes)
- op1 = regFetch(dest)
- else:
- (sreg, offset) = GetOffset(modrm_byte,ads,sreg)
- op1 = lg_read(sreg, offset, n_bytes)
- # op2 = op1
- regStore(source, op1)
- result = sum(op1, temp, n_bytes << 3)
- if modrm_byte >= 0xc0:
- regStore(dest, result)
- else:
- lg_write(sreg, offset, result, n_bytes)
- def DoXch(byte,sreg,ads,os,lock_flag = 0):
- if byte >= 0x90:
- n_bytes = operand_size(os, 1)
- dest = regCode(0, n_bytes) # EAX = 0
- source = regCode(byte & 7, n_bytes)
- x = regFetch(source)
- regStore(source, regFetch(dest))
- regStore(dest, x)
- else:
- n_bytes = operand_size(os, byte - 0x86)
- byte = fetch_code(1)
- dest = regCode((byte >> 3)&7, n_bytes)
- if byte >= 0xc0 and lock_flag:
- raise x86exception('fault', 6, -1,"Invalid instruction")
- elif byte >= 0xc0:
- source = byte & 7
- source = regCode(source, n_bytes)
- x = regFetch(source)
- regStore(source, regFetch(dest))
- regStore(dest, x)
- else:
- sreg, offset = GetOffset(byte, ads, sreg)
- imm_num = lg_read(sreg,offset,n_bytes)
- x = imm_num
- imm_num = regFetch(dest)
- regStore(dest, x)
- lg_write(sreg, offset, imm_num, n_bytes)
- def Xlat(byte, ads):
- n_bytes = ads >> 3
- base = regFetch(regCode(3, n_bytes)) # EBX or BX
- pointer = base + regFetch(16) # AL
- regStore(16, lg_read(DS, pointer, 1)) # AL(16) # AL
- def handle_repeat(n_addressbytes):
- counter_reg = regCode(1,n_addressbytes)
- regStore(counter_reg, regFetch(counter_reg) -1)
- if signal.pending_repeat == "REP":
- if regFetch(counter_reg) == 0:
- signal.pending_repeat = ''
- else:
- EIP.setvalue(EIP.getvalue() - 1)
- elif signal.pending_repeat == "REPE":
- if regFetch(counter_reg) == 0 or Flags["ZF"].getValue() == 1:
- signal.pending_repeat = ''
- else:
- EIP.setvalue(EIP.getvalue() - 1)
- elif signal.pending_repeat == "REPNE":
- if regFetch(counter_reg) == 0 or Flags["ZF"].getValue() == 0:
- signal.pending_repeat = ''
- else:
- EIP.setvalue(EIP.getvalue() - 1)
- def dif(a,b,n_bits,carry_flag=0):
- assert n_bits in [8,16,32], str(n_bits)
- d = a - b - carry_flag
- if (a & 15) - (b & 15) - carry_flag < 0:
- Flags["AF"].setValue(1) # AF = 1
- else:
- Flags["AF"].setValue(0) # AF = 0
- if a >= 1 << (n_bits -1):
- az = a - (1 << n_bits)
- else:
- az = a
- if b >= 1 << (n_bits -1):
- bz = b - (1 << n_bits )
- else:
- bz = b
- dz = az - bz - carry_flag
- if dz < - (1 << (n_bits - 1)) or dz >= (1 << (n_bits - 1)):
- Flags["OF"].setValue(1) # OF = 1
- else:
- Flags["OF"].setValue(0) # OF = 0
- if d < 0:
- Flags["CF"].setValue(1) # CF = 1
- d = d + (1 << n_bits)
- else:
- Flags["CF"].setValue(0) # CF = 0
- if d == 0:
- Flags["ZF"].setValue(1) # ZF = 1
- else:
- Flags["ZF"].setValue(0) # ZF = 0
- if d >= (1 <<(n_bits -1)):
- Flags["SF"].setValue(1) # SF = 1
- else:
- Flags["SF"].setValue(0) # SF = 0
- Flags["PF"].setValue(evenParity(d))
- return d
- def sum(a,b,n_bits,carry_flag=0):
- d = a + b + carry_flag
- if (a & 15) + (b & 15) + carry_flag >= 16:
- Flags["AF"].setValue(1) # AF = 1
- else:
- Flags["AF"].setValue(0) # AF = 0
- if a >= 1 << (n_bits -1):
- az = a - (1 << n_bits)
- else:
- az = a
- if b >= 1 << (n_bits -1):
- bz = b - (1 << n_bits)
- else:
- bz = b
- dz = az + bz + carry_flag
- if dz < - (1 << (n_bits - 1)) or dz >= (1 << (n_bits - 1)):
- Flags["OF"].setValue(1) # OF = 1
- else:
- Flags["OF"].setValue(0) # OF = 0
- if d >= 1<< n_bits:
- Flags["CF"].setValue(1) # CF = 1
- d = d - (1 << n_bits)
- else:
- Flags["CF"].setValue(0) # CF = 0
- if d == 0:
- Flags["ZF"].setValue(1) # ZF = 1
- else:
- Flags["ZF"].setValue(0) # ZF = 0
- if d >= 1 << (n_bits -1):
- Flags["SF"].setValue(1) # SF = 1
- else:
- Flags["SF"].setValue(0) # SF = 0
- Flags["PF"].setValue(evenParity(d))
- return d
- def bblog(a,b,oper_num,n_bits):
- """Binary bitwise logic operations"""
- if oper_num == 1:
- c = a|b
- elif oper_num == 4:
- c = a&b
- elif oper_num == 6:
- c = a^b
- if c >= 1<< (n_bits -1):
- Flags["SF"].setValue(1) # SF = 1
- else:
- Flags["SF"].setValue(0) # SF = 0
- if c == 0:
- Flags["ZF"].setValue(1) # ZF = 1
- else:
- Flags["ZF"].setValue(0) # ZF = 0
- Flags["OF"].setValue(0) # OF = 0
- Flags["CF"].setValue(0) # CF = 0
- Flags["AF"].setValue(random.randint(0,1))
- Flags["PF"].setValue(evenParity(c))
- return c
- def evenParity(x,numbits=8):
- retval = 1
- y = x
- for k in range(numbits):
- retval = retval ^ (y & 1)
- y = y >> 1
- return retval
- def push(value,n_bytes):
- #
- # p 116
- #
- #if descrVec[SS].DefaultAttr:
- stack_reg = 4 #ESP
- #else:
- # stack_reg = 12 #SP
- pointer = regFetch(stack_reg) - n_bytes
- lg_write(2, pointer, value, n_bytes) # 2 = SS
- regStore(stack_reg,pointer)
- def pop(n_bytes):
- #
- # p 118
- #
- #if descrVec[SS].DefaultAttr:
- stack_reg = 4 #ESP
- #else:
- # stack_reg = 12 #SP
- pointer = regFetch(stack_reg)
- retval = lg_read(2, pointer, n_bytes) # 2 = SS
- pointer = pointer + n_bytes
- regStore(stack_reg,pointer)
- return retval
- def prod(a,b,n_bytes):
- c = a * b
- if n_bytes == 1:
- x = c & 255
- y = c >> 8
- flags = (c >= 256)
- regStore(16, x) # AL
- regStore(20, y) # AH
- elif n_bytes == 2:
- x = c & 65535
- y = c >> 16
- flags = (c >= 65536)
- regStore(8, x) # AX
- regStore(10, y) # DX
- elif n_bytes == 4:
- x = c & 0xffffffff
- y = c >> 32
- flags = (c >= 0x100000000)
- regStore(0, x) # EAX
- regStore(2, y) # EDX
- Flags["CF"].setValue(int(flags))
- Flags["OF"].setValue(int(flags))
- Flags["SF"].setValue(random.randint(0,1))
- Flags["ZF"].setValue(random.randint(0,1))
- Flags["AF"].setValue(random.randint(0,1))
- Flags["PF"].setValue(random.randint(0,1))
- return (y,x)
- def signed_prod(a,b,n_bytes,third_arg=None):
- if n_bytes == 1:
- if a > 127:
- a = a - 256
- if b > 127:
- b = b - 256
- c = a * b
- flags = (c > 127 or c < -128)
- if c < 0:
- c = c + 256
- x = c & 255
- y = c >> 8
- # flags = (c >= 256)
- # regStore(AL, x)
- # regStore(AH, y)
- elif n_bytes == 2:
- if a > 32767:
- a = a - 65536
- if b > 32767:
- b = b - 65536
- c = a * b
- flags = (c > 32767 or c < -32768)
- if c < 0:
- c = c + 65536
- x = c & 65535
- y = c >> 16
- # flags = (c >= 65536)
- # regStore(AX, x)
- # regStore(DX, y)
- elif n_bytes == 4:
- if a > 0x7fffffff:
- a = a - 0x100000000
- if b > 0x7fffffff:
- b = b - 0x100000000
- c = a * b
- flags = (c > 0x7fffffff or c < -0x80000000)
- if c < 0:
- c = c + 0x10000000000000000
- x = c & 0xffffffff
- y = c >> 32
- # flags = (c >= 0x100000000)
- # regStore(EAX, x)
- # regStore(EDX, y)
- Flags["CF"].setValue(int(flags))
- Flags["OF"].setValue(int(flags))
- Flags["SF"].setValue(random.randint(0,1))
- Flags["ZF"].setValue(random.randint(0,1))
- Flags["AF"].setValue(random.randint(0,1))
- Flags["PF"].setValue(random.randint(0,1))
- return (y,x)
- def divide(a,b,n_bytes):
- if b == 0:
- raise x86exception('fault', 0, -1,"Division overflow")
- q = a // b
- r = a % b
- if q >= (1 << (n_bytes << 3)):
- raise x86exception('fault', 0, -1,"Division overflow")
- Flags["SF"].setValue(random.randint(0,1))
- Flags["ZF"].setValue(random.randint(0,1))
- Flags["AF"].setValue(random.randint(0,1))
- Flags["PF"].setValue(random.randint(0,1))
- Flags["CF"].setValue(random.randint(0,1))
- Flags["OF"].setValue(random.randint(0,1))
- return (r,q)
- def signed_divide(a,b,n_bytes):
- if b == 0:
- raise x86exception('fault', 0, 0, "Division Overflow")
- if n_bytes == 1:
- a_neg = (a > 32767)
- b_neg = (b > 127)
- if a_neg:
- a = 65536 - a
- if b_neg:
- b = 256 - b
- q = a // b
- if q > 128 or a_neg == b_neg and q == 128:
- raise x86exception('fault', 0, 0, "Division Overflow")
- r = a % b
- if r == 0:
- if a_neg != b_neg:
- q = 256 - q
- else:
- if a_neg != b_neg:
- q = 255 - q
- r = b - r
- if b_neg:
- r = 256 - r
- # regStore(AL, q)
- # regStore(AH, r)
- elif n_bytes == 2:
- a_neg = (a > 0x7fffffff)
- if a_neg:
- a = 0x100000000 - a
- b_neg = (b > 32767)
- if b_neg:
- b = 65536 - b
- q = a // b
- if q > 65536 or a_neg == b_neg and q == 65536:
- raise x86exception('fault', 0, 0, "Division Overflow")
- r = a % b
- if r == 0:
- if a_neg != b_neg:
- q = 65536 - q
- else:
- if a_neg != b_neg:
- q = 65535 - q
- r = b - r
- if b_neg:
- r = 65536 - r
- # regStore(AX, q)
- # regStore(DX, r)
- elif n_bytes == 4:
- a_neg = (a > 0x7fffffffffffffff)
- if a_neg:
- a = 0x10000000000000000 - a
- b_neg = (b > 0x7fffffff)
- if b_neg:
- b = 0x100000000 - b
- q = a//b
- if q > 0x100000000 or a_neg == b_neg and q == 0x100000000:
- raise x86exception('fault', 0, 0, "Division Overflow")
- r = a % b
- if r == 0:
- if a_neg != b_neg:
- q = 0x100000000 - q
- else:
- if a_neg != b_neg:
- q = 0xffffffff - q
- r = b - r
- if b_neg:
- r = 0x100000000 - r
- # regStore(EAX, q)
- # regStore(EDX, r)
- Flags["CF"].setValue(random.randint(0,1))
- Flags["OF"].setValue(random.randint(0,1))
- Flags["SF"].setValue(random.randint(0,1))
- Flags["ZF"].setValue(random.randint(0,1))
- Flags["AF"].setValue(random.randint(0,1))
- Flags["PF"].setValue(random.randint(0,1))
- return (r,q)
- def input_data(datum):
- try:
- num = int(datum)
- except:
- print_feedback("Bad input ")
- return
- if signal.input_register == 0: # EAX
- n_bits = 32
- elif signal.input_register == 8: # AX
- n_bits = 16
- elif signal.input_register == 16: # AL
- n_bits = 8
- else:
- n_bits = 1 << ((signal.input_register & 3) + 2)
- n_bytes = n_bits >> 3
- pointer_reg = signal.input_register | 3 # EDI or DI
- n_address_bytes = 32 // (pointer_reg + 1)
- if num < 1<< n_bits and num >= -(1<<(n_bits -1)):
- if num < 0:
- num = num + (1 << n_bits)
- if signal.input_register & 7 == 0:
- regStore(signal.input_register,num)
- else:
- lg_write(ES, regFetch(pointer_reg), num, n_bytes)
- if Flags["DF"].getValue() == 0:
- regStore(pointer_reg, regFetch(pointer_reg) + n_bytes)
- else:
- regStore(pointer_reg, regFetch(pointer_reg) - n_bytes)
- if signal.pending_repeat:
- handle_repeat(n_address_bytes)
- assert prog.execstate == 'blocked'
- prog.set_current_inst(instoffset = (EIP.getvalue() - prog.load_origin))
- prog.set_execstate(prog.previous_state)
- else:
- print_feedback("input not in " + str(n_bits) + " bit range ")
- #
- # End of the Fetch Execute Section
- #
- ##############################################################
- #
- # x86 Program section.
- #
- ##############################################################
- class Line:
- count = 0
- def __init__(self, source, processed_line):
- self.instoffset = 0
- self.label = ''
- self.mnemonic = ''
- self.displabel = ''
- self.dispcode = 0
- # dispwidth = 1 << ((dispcode & 7) >> 1)
- self.source = source
- self.hexcode = processed_line
- self.instlen = len(processed_line)>>1
- class Program:
- def __init__(self, load_origin = 0):
- dummy_line = Line("Place holder", '')
- dummy_line.instoffset = -1
- terminal_line = Line("Terminal Line", '')
- self.codelist = [dummy_line, terminal_line]
- self.viewlist = []
- self.current_inst = 1
- self.call_depth = 0
- self.filename = ''
- self.execstate = 'inserting'
- self.previous_state = ''
- self.pace = 1000 # milliseconds
- self.unresolved_labels = []
- self.duplicate_labels = []
- self.label_resolve = {}
- self.stored_command = ''
- self.execstack = []
- self.execstackpointer = 0
- self.store_origin = -32
- self.tabwidth = 8
- self.editstack = []
- self.load_origin = load_origin
- def set_execstate(self, new_state):
- assert new_state in ['inserting', 'changing', 'stepping', 'blocked', 'interpreting','running']
- old_state = self.previous_state
- self.previous_state = self.execstate
- self.execstate = new_state
- if old_state == 'interpreting':
- self.viewlist[self.current_inst - 1].configure(background = "yellow")
- if new_state == 'inserting':
- entrybox.configure(state = NORMAL)
- userbox_label.configure(background = "orange")
- userbox_label.configure(text = "Enter Command:")
- entrybox.focus_force()
- elif new_state == 'changing':
- entrybox.configure(state = NORMAL)
- userbox_label.configure(background = "orange")
- userbox_label.configure(text = "Edit Command:")
- entrybox.focus_force()
- elif new_state == 'stepping':
- entrybox.configure(state = DISABLED)
- self.refresh()
- self.execstate = new_state
- userbox_label.configure(background = "green")
- userbox_label.configure(text = "Enter Command:")
- RunBtn.configure(state = NORMAL)
- elif new_state == 'blocked':
- userbox_label.configure(background = "red")
- userbox_label.configure(text = "Enter data:")
- root.after(self.pace, accept_input)
- if self.previous_state == 'running':
- root.after(self.pace, accept_input)
- else:
- accept_input()
- elif new_state == 'running':
- entrybox.configure(state = DISABLED)
- userbox_label.configure(background = "green")
- userbox_label.configure(text = "Enter Command:")
- root.after(self.pace, walk)
- elif new_state == 'interpreting':
- entrybox.configure(state = NORMAL)
- userbox_label.configure(background = "yellow")
- userbox_label.configure(text = "Enter Command:")
- # print("self.current_inst = ", self.current_inst)
- if self.current_inst + 1 < len(self.viewlist):
- self.viewlist[self.current_inst - 1].configure(background = "green")
- entrybox.focus_force()
- def set_current_inst(self, instoffset= None, instnum = None):
- if self.execstate == 'interpreting':
- background_color = "green"
- else:
- background_color = "yellow"
- if instnum == None:
- for k in range(1,len(self.codelist)):
- if self.codelist[k].instoffset == instoffset:
- self.current_inst = k
- self.viewlist[k-1].configure(background = background_color)
- elif self.viewlist[k-1]["background"] != 'white':
- self.viewlist[k-1].configure(background = 'white')
- else:
- address = self.load_origin
- for k in range(len(self.codelist)-1):
- if k == instnum:
- self.current_inst = k + 1
- self.viewlist[k].configure(background = background_color)
- EIP.setvalue(address)
- elif self.viewlist[k]["background"] != 'white':
- self.viewlist[k].configure(background = 'white')
- address = address + self.codelist[k+1].instlen
- def instdelete(self):
- current_instruction = self.current_inst
- line = self.codelist[current_instruction]
- current_offset = line.instoffset
- n_bytes_removed = line.instlen
- if line.label:
- if line.label in self.label_resolve:
- labelled_lines = self.label_resolve[line.label]
- if len(labelled_lines) == 1:
- del self.label_resolve[line.label]
- else:
- labelled_lines.remove(current_instruction)
- # self.label_resolve[line.label] = labelled_lines
- self.editstack.append(self.codelist[current_instruction])
- del self.codelist[current_instruction]
- self.textslide(current_instruction , n_bytes_removed, '-')
- self.fixjumps()
- def instinsert(self,line):
- current_instruction = self.current_inst
- current_offset = self.codelist[current_instruction].instoffset
- line.instoffset = current_offset
- n_bytes_added = line.instlen
- self.textslide(current_instruction, n_bytes_added, '+')
- self.codelist[current_instruction:current_instruction]= [line]
- if line.label:
- # self.label_resolve[line.label] = current_instruction
- if line.label in self.label_resolve:
- self.label_resolve[line.label].append(current_instruction)
- else:
- self.label_resolve[line.label] = [current_instruction]
- #resolve labels in line just added
- while 1:
- for index, lin in enumerate(self.codelist):
- if not lin.displabel:
- continue
- target_num = self.label_resolve.get(lin.displabel,1)
- if target_num != 1:
- target = target_num[0]
- else:
- target = 1
- # target = self.codelist[self.label_resolve.get(lin.displabel,1)].instoffset
- target = self.codelist[target].instoffset
- jump = target - lin.instoffset - lin.instlen
- if lin.dispwidth == 1:
- if -128 <= jump < 128:
- continue
- elif Use_size.get() == 16 and lin.hexcode[0] == '7': #Conditional jump
- self.textslide(index + 1, 2, '+')
- lin.instlen = lin.instlen + 2
- lin.dispwidth = 2
- if jump < 0:
- lin.hexcode= '0F8' + hexcode[1] + byte_swap("%04X" % (jump+ 65536))
- else:
- lin.hexcode= '0F8' + hexcode[1] + byte_swap("%04X" % jump)
- elif Use_size.get() == 16 : #Unconditional jump
- self.textslide(index + 1, 1, '+')
- lin.instlen = lin.instlen + 1
- lin.dispwidth = 4
- if jump < 0:
- lin.hexcode= 'E9' + byte_swap("%04X" % (jump+ 65536))
- else:
- lin.hexcode= 'E9' + byte_swap("%04X" % jump)
- elif lin.hexcode[0] == '7': #Conditional jump
- self.textslide(index + 1, 4, '+')
- lin.instlen = lin.instlen + 4
- lin.dispwidth = 4
- if jump < 0:
- lin.hexcode= '0F8' + hexcode[1] + byte_swap("%08X" % (jump+(1<<32)))
- else:
- lin.hexcode= '0F8' + hexcode[1] + byte_swap("%08X" % jump)
- elif lin.hexcode[:2] == 'EB': #Unconditional jump
- self.textslide(index + 1, 3, '+')
- lin.instlen = lin.instlen + 3
- lin.dispwidth = 4
- if jump < 0:
- lin.hexcode= 'E9' + byte_swap("%08X" % (jump+(1<<32)))
- else:
- lin.hexcode= 'E9' + byte_swap("%08X" % jump)
- break
- elif lin.dispwidth == 2:
- if -32768 <= jump < 32768:
- continue
- else:
- print("Very long jump.")
- raise SystemExit
- elif lin.dispwidth == 4:
- continue
- else:
- break
- self.fixjumps()
- def textslide(self,index,n_bytes, sign):
- for i,lin in enumerate(self.codelist):
- if i >= index:
- if sign == '+':
- lin.instoffset += n_bytes
- else:
- lin.instoffset -= n_bytes
- for label in self.label_resolve:
- # if self.label_resolve[label] >= index:
- # if sign == '+' :
- # self.label_resolve[label] += 1
- # else:
- # self.label_resolve[label] -= 1
- newlist = []
- for target in self.label_resolve[label]:
- if target >= index:
- if sign == '+':
- newlist.append(target + 1)
- else:
- newlist.append(target - 1)
- else:
- newlist.append(target)
- self.label_resolve[label] = newlist
- def fixjumps(self):
- bad_list = []
- repeat_list = []
- for lin in self.codelist:
- if not lin.displabel:
- continue
- target_list = self.label_resolve.get(lin.displabel,1)
- if target_list == 1:
- if lin.displabel not in bad_list:
- bad_list.append(lin.displabel)
- target_num = 1
- elif len(target_list) > 1:
- target_num = target_list[0]
- if lin.displabel not in repeat_list:
- repeat_list.append(lin.displabel)
- else:
- target_num = target_list[0]
- # target = self.codelist[self.label_resolve.get(lin.displabel,1)].instoffset
- target = self.codelist[target_num].instoffset
- jump = target - lin.instoffset - lin.instlen
- if lin.dispwidth == 1 and jump < 0:
- lin.hexcode = lin.hexcode[:-2] + "%02X"%(jump + 256)
- elif lin.dispwidth == 1:
- lin.hexcode = lin.hexcode[:-2] + "%02X"% jump
- elif lin.dispwidth == 2 and jump < 0:
- lin.hexcode = lin.hexcode[:-4] + byte_swap("%04X"%(jump + 65536))
- elif lin.dispwidth == 2:
- lin.hexcode = lin.hexcode[:-4] + byte_swap("%04X"% jump )
- elif lin.dispwidth == 4 and jump < 0:
- lin.hexcode = lin.hexcode[:-8] + byte_swap("%08X"%(jump + (1<<32)) )
- elif lin.dispwidth == 4 :
- lin.hexcode = lin.hexcode[:-8] + byte_swap("%08X"% jump)
- self.unresolved_labels = bad_list
- self.duplicate_labels = repeat_list
- def store(self):
- pointer = self.load_origin
- for lin in self.codelist:
- for k in range(lin.instlen):
- byte_val = int(lin.hexcode[2*k:2*k + 2],16)
- LA_write(pointer, byte_val,1)
- pointer = pointer + 1
- def codelin(self):
- cl = StringVar()
- m = Label(codePanel.interior,borderwidth=0,
- anchor = "w",
- relief=SUNKEN,
- textvariable=cl,
- width = 32,
- background = "white",
- font = "Courier 12 bold")
- cl.set(' ')
- m.value = cl
- m.bind('<Button-1>', self.select_line)
- m.bind('<Button-3>', self.show_hex)
- return m
- def select_line(self, event):
- if self.execstate != 'inserting' and self.execstate != 'stepping':
- self.set_execstate('stepping')
- for i,x in enumerate(self.viewlist):
- if event.widget == x:
- EIP.setvalue(self.codelist[i+1].instoffset)
- self.set_current_inst(instnum = i)
- def show_hex(self, event):
- for i,x in enumerate(self.viewlist):
- if event.widget == x:
- print_feedback(self.codelist[i+1].hexcode + ' ')
- def refresh(self):
- for m in self.viewlist:
- m.pack_forget()
- self.viewlist = []
- if self.execstate == 'interpreting':
- background_color = "green"
- else:
- background_color = "yellow"
- for i,x in enumerate(self.codelist):
- if i == 0:continue
- m = self.codelin()
- m.value.set(x.source.rstrip())
- self.viewlist.append(m)
- if i + 1 == len(self.codelist): continue
- m.pack(side = TOP, fill = X, expand = YES)
- if self.current_inst == i:
- m.configure(background = background_color)
- #################################################################
- #
- # Memory Section
- #
- #################################################################
- class Memlin(Label):
- def __init__(self, parent, n_bytes = 8):
- viewing_line = StringVar()
- Label.__init__(self,parent,borderwidth=0,relief=SUNKEN,width=32,
- textvariable=viewing_line,
- background="white",font="Courier 12 bold")
- viewing_line.set(' ')
- self.textvariable = viewing_line
- self.width = n_bytes
- def setvalue(self, value):
- assert type(value) is tuple and len(value) in [5,9]
- if self.width == 8:
- row = "%02X %02X%02X%02X%02X %02X%02X%02X%02X"
- elif self.width ==4:
- row = "%02X %02X%02X%02X%02X"
- self.textvariable.set(row % value)
- class Memory:
- def __init__(self, addr_bits, panel):
- self.length = (1 << addr_bits)
- self.addr_bits = addr_bits
- self.vec = array.array('B', [0 for x in range(self.length)])
- self.viewbase = 0
- self.panel = panel
- self.memlist = self.build_memlist()
- def read(self,phys_addr,n_bytes):
- if phys_addr + n_bytes <= self.length:
- retval = 0
- for k in range(n_bytes):
- retval = retval + (self.vec[phys_addr + k] << (k << 3))
- return retval
- # See Agarwal page 91 for a description of the following wrap-around behavior.
- mask = self.length - 1
- retval = 0
- for k in range(n_bytes):
- retval = retval + (self.vec[(phys_addr + k) & mask] << (k << 3))
- return retval
- def read_n_bytes(self, physaddr,n_bytes = 8):
- if n_bytes == 8:
- mask = 248
- elif n_bytes == 4:
- mask = 252
- retlist = [physaddr & -n_bytes] + list(self.vec[physaddr:physaddr + n_bytes])
- return tuple(retlist)
- def write(self,phys_addr, value, n_bytes):
- assert phys_addr + n_bytes <= self.length
- assert n_bytes > 0
- if phys_addr + n_bytes <= self.length:
- for k in range(n_bytes):
- self.vec[phys_addr + k] = (value & 255)
- value = (value >> 8)
- else:
- mask = self.length - 1
- for k in range(n_bytes):
- self.vec[(phys_addr + k) & mask] = (value & 255)
- value = (value >> 8)
- def build_memlist(self):
- ml = []
- for x in range(self.viewbase, self.viewbase + 192,8):
- newline = Memlin(self.panel)
- newline.pack(side = TOP)
- ml.append(newline)
- return ml
- def refresh(self):
- x = self.viewbase
- for ml in self.memlist:
- ml.setvalue(self.read_n_bytes(x))
- x = x + 8
- class MemView:
- def __init__(self,panel,width = 8):
- self.panel = panel
- self.memlist = []
- self.viewbase = 0
- self.width = width
- for x in range(self.viewbase, self.viewbase + 192,8):
- newline = Memlin(self.panel)
- newline.pack(side = TOP)
- self.memlist.append(newline)
- def refresh(self):
- x = self.viewbase
- for ml in self.memlist:
- ml.setvalue(mem.read_n_bytes(x, self.width))
- x = x + self.width
- ##############################################################
- #
- # x86 Architecture
- #
- ##############################################################
- class Viewable_Register:
- def __init__(self, num_bits, name):
- self.strvalue = StringVar()
- self.bitlength = num_bits
- self.formatString = " %0" + str(self.bitlength >> 2) + "X"
- self.strvalue.set(self.formatString % 0)
- self.name = name
- def setValue(self,new_value):
- assert 0 <= new_value < 1 << self.bitlength
- self.strvalue.set(self.formatString % new_value)
- def getValue(self):
- return int(self.strvalue.get(),16)
- class Viewable_Boolean:
- def __init__(self, name):
- self.strvalue = StringVar()
- # self.formatString = " %0" + str(self.bitlength >> 2) + "X"
- self.formatString = " %01X"
- self.strvalue.set(self.formatString % 1)
- self.name = name
- def setValue(self,new_value):
- if type(new_value) is bool:
- if new_value:
- self.strvalue.set(self.formatString % 1)
- else:
- self.strvalue.set(self.formatString % 0)
- elif type(new_value) is int:
- if new_value == 0:
- self.strvalue.set(self.formatString % 0)
- else:
- self.strvalue.set(self.formatString % 1)
- def getValue(self):
- return bool(int(self.strvalue.get()))
- class Modifiable_Register(Frame):
- def __init__(self,regname,numbits):
- Frame.__init__(self)
- self.grid()
- lbl = Label(self, background = "red",
- foreground = "yellow",
- text = regname,
- width = 5,
- font = "Arial 20")
- lbl.pack(side = "left")
- self.value_box = Entry(self,width = 12, background = "white",
- font ="Courier 20 bold")
- self.value_box.pack()
- self.value_box.bind("<Return>",self.enterValue)
- self.bitlength = numbits
- self.value= "".join(random.sample("0123456789ABCDEF",8))
- self.value_box.insert(0, " " + self.value )
- def enterValue(self,event):
- text = event.widget.get()
- save_old = int(self.getStringValue(),16)
- save_old = self.getValue()
- try:
- new_value = int(text,16)
- except:
- new_value = save_old
- if 0 > new_value or new_value >= 1<< self.bitlength:
- new_value = save_old
- self.setValue(new_value)
- def getStringValue(self):
- return self.value
- def setValue(self,new_value):
- assert 0 <= new_value < 1 << self.bitlength
- self.value = "%08X"% new_value
- self.value_box.delete(0,END)
- self.value_box.insert(END, " " + self.value )
- def getValue(self):
- return int(self.value,16)
- class InstructionPointer:
- def __init__(self, size):
- self.value = 0
- def setvalue(self, new_value):
- assert new_value < (1<<32)
- self.value = new_value
- def getvalue(self):
- return self.value
- class Flag(Frame):
- def __init__(self,flagname):
- Frame.__init__(self)
- lbl = Label(self, background = "gray",
- foreground = "white",
- text = flagname,
- width = 3,
- relief = SUNKEN,
- font = "Arial 20")
- lbl.pack(side = "left",padx=3)
- lbl.bind("<Button-1>", self.toggleValue)
- self.value = 0
- self.label = lbl
- def setValue(self,new_value):
- assert new_value == 0 or new_value == 1
- self.value = new_value
- if new_value == 0:
- self.label.configure(background = "gray",foreground="white")
- else:
- self.label.configure(background = "black",foreground = "orange")
- def getValue(self):
- return self.value
- def toggleValue(event,d):
- flag = event
- flag.setValue(1 - flag.getValue())
- class Descr:
- def __init__(self):
- # See Agarwal pp 32, 33.
- self.Base = Viewable_Register(32,"Base")
- self.Base.setValue(0)
- self.Limit = Viewable_Register(32,"Limit")
- self.Limit.setValue(0xffffffff)
- self.DPL = Viewable_Register(2,"DPL")
- self.DPL.setValue(0)
- self.Valid = Viewable_Boolean("Valid")
- self.Valid.setValue(True)
- self.CDSeg = Viewable_Boolean("CDSeg")
- self.CDSeg.setValue(True)
- self.Readable = Viewable_Boolean("Readable")
- self.Readable.setValue(True)
- self.Writable = Viewable_Boolean("Writable")
- self.Writable.setValue(True)
- self.Executable = Viewable_Boolean("Executable")
- self.Executable.setValue(True)
- self.Conforming = Viewable_Boolean("Conforming")
- self.Conforming.setValue(True)
- self.ExpandDown = Viewable_Boolean("ExpandDown")
- self.ExpandDown.setValue(False)
- self.Type = Viewable_Register(4,"Type")
- self.Type.setValue(0)
- self.DefaultAttr = Viewable_Boolean("DefaultAttr")
- self.DefaultAttr.setValue(True)
- self.GDField = Viewable_Register(4,"GDField")
- self.GDField.setValue(0)
- self.Accessed = Viewable_Boolean("Accessed")
- self.Accessed.setValue(False)
- self.Selector = Viewable_Register(16,"Selector")
- self.Selector.setValue(0)
- self.Offset = Viewable_Register(32,"Offset")
- self.Offset.setValue(0)
- self.ParamCount = Viewable_Register(4,"ParamCount")
- self.ParamCount.setValue(0)
- def read_descr(self, sel, TSS_load):
- # Read descriptor and write into desc
- # pp 63-66
- erc = sel & 0xFFFC
- if (sel & 4) == 0:
- tableDesc = descrVec[GDT]
- else:
- tableDesc = descrVec[LDT]
- sel_Index = sel & 0xfff8
- d1 = DTAB_read(erc, tableDesc, sel_Index, TSS_load, 4)
- d2 = DTAB_read(erc, tableDesc, sel_Index + 4, TSS_load, 4)
- self.Valid.setValue(bool(d2 & (1 << 15)))
- self.DPL.setValue((d2 >> 13) & 3) # Bits 13,14
- self.CDSeg.setValue(bool(d2 & (1 << 12))) # Bit 12
- if self.CDSeg.getValue():
- self.Base.setValue((((d2 >> 24) & 255) << 24) | ((d2 & 255) << 16)| (d1 >>16))
- self_Limit = (((d2 >> 16) & 15) << 16) + (d1 & 65535)
- if d2 & (1 << 23): # Page granularity
- self.Limit.setValue((self_Limit << 12) + 0xfff)
- else:
- self.Limit.setValue(self_Limit)
- self.DefaultAttr.setValue(d2 & (1 << 22))
- self.Executable.setValue(d2 & (1 << 11))
- if self.Executable.getValue():
- self.Conforming.setValue(d2 & (1<< 10))
- self.Readable.setValue(d2 & (1<< 9))
- self.Writable.setValue(False)
- self.ExpandDown.setValue(False)
- else:
- self.ExpandDown.setValue(d2 & (1 << 10))
- self.Writable.setValue(d2 & (1 << 9))
- self.Readable.setValue(True)
- self.Conforming.setValue(False)
- self.Type.setValue(0)
- else:
- self.Type.setValue((d2 >> 8) & 15)
- self.Selector.setValue(d1 >> 16)
- self.Offset.setValue((d2 >> 16)<< 16) | (d1 & 65535)
- self.Executable = False
- if self.Type.getValue() in [1,2,3,9,11]:
- # LDT_SEG,NOTBUSY_TSS16,BUSY_TSS16,NOTBUSY_TSS32,BUSY_TSS32
- self.Readable.setValue(True)
- self.Writable.setValue(True)
- else:
- self.Readable.setValue(False)
- self.Writable.setValue(False)
- self.ParamCount.setValue(d2 & 31)
- self.Accessed.setValue(d2 & 256)
- self.GDField.setValue((d2 >> 20) & 15)
- def write_descr(self, phys_addr):
- # The x86 cannot do this. This is for the edlinas user only.
- d2 = 0
- if self.Valid.getValue():
- d2 = d2 | (1 << 15)
- d2 = d2 | (self.DPL.getValue() << 13)
- d2 = d2 | (int(self.CDSeg.getValue()) << 12)
- if self.CDSeg.getValue() or self.Type.getValue() in [1,2,3,9,11]:
- # LDT_SEG,NOTBUSY_TSS16,BUSY_TSS16,NOTBUSY_TSS32,BUSY_TSS32
- d1 = (self.Base.getValue() & 0xffff)<< 16
- if self.GDField.getValue() & 8:
- d1 = d1 | ((self.Limit.getValue() >> 12) & 0xffff)
- d2 = d2 | ((self.Limit.getValue() >> 12) & 0xf0000)
- else:
- d1 = d1 | (self.Limit.getValue() & 0xffff)
- d2 = d2 | (self.Limit.getValue() & 0xf0000)
- d2 = d2 |(self.Base.getValue() & 0xff000000)|((self.Base.getValue() & 0xff0000) > 16)
- d2 = d2 |(self.GDField.getValue() << 20)
- if self.CDSeg.getValue():
- d2 = d2 | (1 << 12)
- if self.Executable.getValue():
- d2 = d2 | (1 << 11)
- if self.Conforming.getValue():
- d2 = d2 | (1 << 10)
- if self.Readable.getValue():
- d2 = d2 | (1 << 9)
- else:
- if self.ExpandDown.getValue():
- d2 = d2 | (1 << 10)
- if self.Writable.getValue():
- d2 = d2 | (1 << 9)
- else:
- d2 = d2 | (self.Type.getValue() << 8)
- else:
- d2 = d2 | (self.Type.getValue() << 8)
- d2 = d2 | (self.Offset.getValue() & 0xffff0000)
- d1 = d1 | (self.Offset.getValue() & 0xffff)
- d1 = d1 | (self.Selector.getValue() << 16)
- d2 = d2 | self.ParamCount.getValue()
- mem.write(phys_addr, d1, 4)
- mem.write(phys_addr + 4, d2, 4)
- class showDescr(Frame):
- def __init__(self, parent,segnum):
- Frame.__init__(self, parent)
- self.grid()
- lbl = Label(self, background = "red",
- foreground = "yellow",
- text = segReg[segnum].name,
- width = 5,
- font = "Arial 20")
- lbl.pack(side = "top")
- m = showReg(self, "Base", 32, descrVec[segnum].Base.strvalue)
- m.pack(side = 'top')
- m = showReg(self, "Limit", 32, descrVec[segnum].Limit.strvalue)
- m.pack(side = 'top')
- m = showReg(self, "Valid", 1, descrVec[segnum].Valid.strvalue)
- m.pack(side = 'left')
- m = showReg(self, "DPL", 1, descrVec[segnum].DPL.strvalue)
- m.pack(side = 'left')
- #
- # This function was modified to change the display behavior for descriptor table
- # entries GDT and IDT. These two will be displayed like normal registers except
- # the entry box for the register value will be grayed out since they are not
- # actual registers. This was done by adding the if/else block to determine if the
- # current register is a actual register or just a descriptor table entry.
- ###
- ### Changed to use reg.value_box.configure(state = DISABLED) after showReg is called
- ###
- class showReg(Frame):
- def __init__(self,parent,regname,numbits,content,source=None):
- Frame.__init__(self,parent)
- # self.grid()
- lbl = Label(self, background = "red",
- foreground = "yellow",
- text = regname,
- width = 5,
- font = "Arial 20")
- lbl.pack(side = "left")
- # if regname=="GDT" or regname=="IDT":
- # self.value_box = Entry(self,width = 2 + (numbits//4), background = "white", font ="Courier 20 bold", textvariable=content, state=DISABLED)
- # else:
- self.value_box = Entry(self,width = 2 + ((numbits + 3)//4), background = "white",
- font ="Courier 20 bold", textvariable=content)
- self.value_box.pack()
- self.value_box.bind("<Return>",self.enterValue)
- self.bitlength = numbits
- self.value = content
- self.source = source
- def enterValue(self,event):
- text = event.widget.get()
- save_old = self.getValue()
- try:
- new_value = int(text,16)
- except:
- new_value = save_old
- if 0 > new_value or new_value >= 1<< self.bitlength:
- new_value = save_old
- self.setValue(new_value)
- if new_value != save_old and self.source:
- source.setValue(new_value)
- def setValue(self,new_value):
- assert 0 <= new_value < 1 << self.bitlength
- formatString = " %0" + str(self.bitlength >> 2) + "X"
- self.value.set(formatString % new_value)
- def getValue(self):
- return int(self.value.get(),16)
- def refresh(self):
- self.setValue(source.getValue())
- class StackView(Frame):
- def __init__(self,parent):
- # stackPanel = Frame(m,width = 200, height = 540, background = "white")
- viewing_line = StringVar()
- Frame.__init__(self,parent,width = 200, height = 540, background = "white")
- self.memlist = []
- self.bottom = genReg[4].getValue() # ESP
- self.bind("<Button-1>", lambda e: e.widget.reset_bottom())
- self.bind('<KeyPress-Down>', lambda e: e.widget.pop_stack())
- self.bind('<KeyPress-Up>', lambda e: e.widget.push_stack())
- def refresh(self):
- for m in self.memlist:
- m.pack_forget()
- stack_pointer = genReg[4].getValue()
- for lin_address in range(self.bottom, stack_pointer, -4):
- memlin = Memlin(self, 4)
- # print(mem.read_n_bytes(lin_address - 4, 4))
- memlin.setvalue(mem.read_n_bytes(lin_address - 4, 4))
- memlin.pack(side = BOTTOM)
- self.memlist.append(memlin)
- def reset_bottom(self):
- self.bottom = genReg[4].getValue() # ESP
- self.refresh()
- def push_stack(self):
- self.bottom = self.bottom + 4
- self.refresh()
- def pop_stack(self):
- self.bottom = self.bottom - 4
- self.refresh()
- # Functions called when memory is setup
- def set_viewbase(event):
- text = event.widget.get()
- save_old = mem.viewbase
- try:
- new_value = int(text,16) &-8
- except:
- new_value = save_old
- if 0 > new_value or new_value >= 1<< mem.addr_bits:
- new_value = save_old
- mem.viewbase = new_value
- event.widget.delete(0,END)
- event.widget.insert(END, "%08X"% new_value)
- mem.refresh()
- def build_membox(root):
- value_box = Entry(root,width = 8, background = "white", font ="Courier 16 bold")
- value_box.place(x = 1006,y=43)
- value_box.insert(END, "%08X"% 0)
- return value_box
- ################################################################
- #
- # Set up GUI
- #
- ###############################################################
- root = Tk()
- root.title("Edlinas")
- root.geometry("1200x740")
- app = Frame(root)
- app.grid()
- app.master["background"]="blue"
- H_16 = "Helvetica -16 bold"
- #################################################################
- #
- # Menu Section
- #
- #################################################################
- mBar = Frame(root, relief = RAISED, borderwidth = 2)
- mBar.place(x = 0, y = 0, width = 1250)
- #
- # File Menu
- #
- def interpret(e = None):
- prog.set_execstate('interpreting')
- return
- def clearscreen():
- global prog
- for m in prog.viewlist:
- m.pack_forget()
- prog = Program()
- prog.refresh()
- def merge_file():
- filename = askopenfilename(defaultextension='.asm',
- initialdir = os.getcwd(),
- title = 'Merge assembler file',
- filetypes = [('assembler','*.asm'),('assembler','*.ASM')])
- if not filename :
- return
- else:
- fetch_file(filename,replace_old = False)
- def save_as_file():
- filename = asksaveasfilename(defaultextension='.asm',
- initialdir = os.getcwd(),
- title = 'Save As',
- filetypes = [('assembler','*.asm'),('assembler','*.ASM')])
- if not filename :
- return
- else:
- save_file(filename)
- def get_file():
- filename = askopenfilename(defaultextension='.asm',
- initialdir = os.getcwd(),
- title = 'Open assembler file',
- filetypes = [('assembler','*.asm'),('assembler','*.ASM')])
- if not filename :
- return
- else:
- fetch_file(filename)
- def fetch_file(filename, replace_old = True):
- if replace_old:
- global prog
- for m in prog.viewlist:
- m.pack_forget()
- prog = Program()
- prog.filename = filename
- open_file(filename)
- def open_file(filename):
- f = open(filename,"r")
- line_num = 1
- for source_line in f:
- line = build_line(source_line.rstrip(), line_num)
- if type(line) is str:
- print_feedback(line)
- return
- prog.instinsert(line)
- prog.current_inst = prog.current_inst + 1
- line_num = line_num + 1
- f.close()
- prog.store()
- mem.refresh()
- prog.filename = filename
- prog.set_execstate('stepping')
- return
- def open_same_file():
- global prog
- if prog.filename :
- for m in prog.viewlist:
- m.pack_forget()
- old_program_name = prog.filename
- prog = Program()
- prog.filename = old_program_name
- open_file(old_program_name)
- prog.refresh()
- else:
- print_feedback("No previous load attempted")
- return
- def save_file(fname=None):
- if fname == None:
- f = open(prog.filename, "w")
- else:
- f= open(fname, "w")
- for k,l in enumerate(prog.codelist):
- if k == 0: continue
- f.write(l.source)
- f.close()
- def makeFileMenu():
- FileBtn = Menubutton(mBar, text = 'File', width = 8, font = H_16, underline= 0)
- FileBtn.pack(side = LEFT, padx = "2m")
- FileBtn.menu = Menu(FileBtn)
- FileBtn.menu.choices = Menu(FileBtn)
- FileBtn.menu.add_command(label = "New",font = H_16, command= clearscreen)
- FileBtn.menu.add_command(label = "Open",font = H_16, command=get_file)
- FileBtn.menu.add_command(label = "Re-open",font = H_16, command=open_same_file)
- FileBtn.menu.add_command(label = "Merge",font = H_16, command=merge_file)
- FileBtn.menu.add_command(label = "Save",font = H_16, command=save_file)
- FileBtn.menu.add_command(label = "Save As",font = H_16, command=save_as_file)
- FileBtn.menu.add_command(label = "Quit",font = H_16, command=FileBtn.quit)
- FileBtn['menu'] = FileBtn.menu
- return FileBtn
- #
- # Make Edit Menu
- #
- def insert_mode():
- prog.set_execstate('inserting')
- return
- def changeline():
- try:
- line = prog.codelist[prog.current_inst]
- except:
- return
- if prog.current_inst + 1 == len(prog.codelist):
- print_feedback("Not a program line.")
- return
- prog.set_execstate('changing')
- entrybox.insert(0,line.source.rstrip())
- def delete_current():
- if prog.current_inst + 1 == len(prog.codelist):
- print_feedback("Not a program line.")
- return
- prog.instdelete()
- prog.store()
- prog.refresh()
- mem.refresh()
- return
- def insert_saved_line():
- if prog.editstack == []:
- return
- old_source = prog.editstack.pop().source
- line = build_line(old_source)
- if type(line) is str:
- return
- prog.instinsert(line)
- prog.store()
- prog.refresh()
- mem.refresh()
- def makeEditMenu():
- EditBtn = Menubutton(mBar, text = 'Edit', width = 8, font = H_16, underline= 0)
- EditBtn.pack(side = LEFT, padx = "2m")
- EditBtn.menu = Menu(EditBtn)
- EditBtn.menu.add_command(label = "Change ",font = H_16, command=changeline)
- EditBtn.menu.add_command(label = "Delete ",font = H_16, command=delete_current)
- EditBtn.menu.add_command(label = "Insert ",font = H_16, command=insert_mode)
- EditBtn.menu.add_command(label = "Paste ",font = H_16, command=insert_saved_line)
- EditBtn['menu'] = EditBtn.menu
- return EditBtn
- #
- # Make Run Menu
- #
- def run_program(e=None):
- reset_execstate()
- if prog.execstate == 'inserting':
- return
- continue_execution()
- def continue_execution(e = None):
- prog.set_execstate('running')
- def walk():
- if prog.execstate == 'running':
- try:
- fetchexec()
- except x86exception as e:
- print_feedback("Exception "+str(e.interrupt_number)+': '+ e.error_message + ' ')
- prog.set_execstate('stepping')
- if prog.execstate == 'running':
- root.after(prog.pace, walk)
- def single_step():
- prog.set_execstate('stepping')
- def block():
- prog.set_execstate('blocked')
- def accept_input():
- entrybox.configure(state = NORMAL)
- entrybox.focus_force()
- userbox_label.configure(text = "Enter data:")
- def reset_execstate():
- if len(prog.duplicate_labels) == 1:
- message = "Duplicate label: " + prog.duplicate_labels[0]
- elif len(prog.duplicate_labels) > 1:
- message = "Duplicate labels: "
- for lbl in prog.duplicate_labels:
- message = message + lbl + " "
- elif len(prog.unresolved_labels) == 1:
- message = "Unresolved label: " + prog.unresolved_labels[0]
- elif len(prog.unresolved_labels) > 1:
- message = "Unresolved labels: "
- for lbl in prog.unresolved_labels:
- message = message + lbl + " "
- else:
- message = ''
- if message:
- print_feedback(message)
- prog.set_execstate('inserting')
- return
- EIP.setvalue(0)
- prog.current_inst = 1
- prog.call_depth = 0
- prog.set_execstate('stepping')
- def makeRunMenu():
- RunBtn = Menubutton(mBar, text = 'Run',width = 8, font = H_16, underline= 0)
- RunBtn.pack(side = LEFT, padx = "2m")
- RunBtn.menu = Menu(RunBtn)
- RunBtn.menu.add_command(label = "Run ",font = H_16, command= run_program)
- RunBtn.menu.add_command(label = "Continue",font = H_16, command=continue_execution)
- RunBtn.menu.add_command(label = "Interpret",font = H_16, command= interpret)
- RunBtn.menu.add_command(label = "Single Step",font = H_16, command= single_step)
- RunBtn.menu.add_command(label = "Reset",font = H_16, command= reset_execstate)
- RunBtn['menu'] = RunBtn.menu
- return RunBtn
- #
- # Make Internals Menu : Call Toplevel Windows for Placed over the Right Panel
- #
- Display_Geometry = "340x595+850+75"
- def displayInternals(RegList, name):
- m = Toplevel(root,width = 100, height = 590)
- m.wm_geometry(Display_Geometry)
- # m.title("Segment Registers")
- m.title(name + " Registers")
- m.wm_attributes("-topmost", 1)
- for ireg in RegList:
- reg = showReg(m, ireg.name, 32, ireg.strvalue)
- reg.pack(side = TOP, pady = 14)
- def displayDebugRegs():
- displayInternals(debReg, "Debug")
- def displayTestRegs():
- displayInternals(testReg, "Test")
- def displayControlRegs():
- displayInternals(ctrlReg, "Control")
- # This function is called from displaySegments when the "More Info" button is pressed next
- # to a register or Descriptor Table entry. If the button is next to a Segment register,
- # this will load the contents of the Segment Register and the matching Descriptor from the
- # Descriptor Table. If the button is pressed next to a Descriptor entry (GDT or IDT), this
- # will just load the Descriptor entry for the selected Table.
- def viewMore(regname,k):
- m = Toplevel(root, width=100, height=300, bg="blue")
- m.title("Descriptor Info")
- m.wm_attributes("-topmost", 1)
- if regname=="GDT" or regname=="IDT":
- reg = showReg(m, regname, 16, "")
- else:
- reg = showReg(m, regname, 16, segReg[k].strvalue)
- reg.grid(row=0)
- spacer0= Label(m, background="blue", text='\n')
- spacer0.grid(row=1)
- seg_info = showDescr(m,k)
- seg_info.config(background="blue")
- seg_info.grid(row=2)
- # This function was modified to correctly display all the Segment Registers and two Descriptor
- # Table entries. The Segment Registers now display correctly in order and two Descriptor Table
- # entiries were added (GDT and IDT). A "More Info" button was provided next to each entry to
- # display additional information from the appropriate descriptor table.
- def displaySegments():
- m = Toplevel(root,width = 100, height = 300, bg="blue")
- # m.wm_geometry(Display_Geometry)
- m.title("Segment Registers")
- m.wm_attributes("-topmost", 1)
- for k, r_name in enumerate(register_names):
- reg = showReg(m, r_name, 16, segReg[k].strvalue)
- reg.grid(row=k, column=0)
- spacer=Label(m, background="blue", text="\t")
- spacer.grid(row=k, column=2)
- view_more_info_btn = Button(m, text="More\nInfo", font = "Courier 10", bd=5, command=lambda k=k,r_name=r_name:viewMore(r_name,k))
- view_more_info_btn.grid(row=k,column=3)
- # reg.value_box.configure(state = DISABLED)
- k=k+1
- r_name="GDT"
- reg=showReg(m, r_name, 16, "")
- reg.grid(row=k, column=0)
- reg.value_box.configure(state = DISABLED)
- spacer=Label(m, background="blue", text="\t")
- spacer.grid(row=k, column=2)
- view_more_info_btn = Button(m, text="More\nInfo", font = "Courier 10", bd=5, command=lambda k=k,r_name=r_name: viewMore(r_name,k))
- view_more_info_btn.grid(row=k,column=3)
- k=k+1
- r_name="IDT"
- reg=showReg(m, r_name, 16, "")
- reg.grid(row=k, column=0)
- reg.value_box.configure(state = DISABLED)
- spacer=Label(m, background="blue", text="\t")
- spacer.grid(row=k, column=2)
- view_more_info_btn = Button(m, text="More\nInfo", font = "Courier 10", bd=5, command=lambda k=k,r_name=r_name: viewMore(r_name,k))
- view_more_info_btn.grid(row=k,column=3)
- #MARK# <--- temporary location marker
- def displayStack():
- global stackWindow, stackView
- if genReg[4].getValue() >= ( 1 << mem.addr_bits):
- print_feedback("Stack pointer is too large.")
- return
- stackWindow = Toplevel(root,width = 200, height = 590)
- stackWindow.wm_geometry(Display_Geometry)
- stackWindow.wm_attributes("-topmost", 1)
- stackWindow.title("Stack")
- l = Label(stackWindow, font = "Arial 20", text = "Stack", background = 'red')
- l.pack(side = TOP,fill = X, expand = NO, pady = 0)
- stackView = StackView(stackWindow)
- stackView.pack(side = TOP, fill= BOTH, expand = YES)
- def bottomInit(panel):
- panel.set_bottom()
- #def displayStatusRegs():
- # m = Toplevel(root,width = 200, height = 600)
- # m.wm_geometry(Display_Geometry)
- # m.title("Control Registers")
- # m.wm_attributes("-topmost", 1)
- # l = Label(m, font = "Arial 20", text = "Control Registers", background = 'red')
- # l.pack(side = TOP,fill = X, expand = NO, pady = 0)
- # stackPanel = Frame(m,width = 200, height = 540, background = "white")
- # stackPanel.pack(side = TOP, fill= BOTH, expand = YES)
- # for k in range(8):
- # reg = showReg(m, "CR" + str(k), 16, segReg[k].strvalue)
- # reg.pack(side = TOP, pady = 14)
- def makePopupMenu():
- PopupBtn = Menubutton(mBar, text = 'Internals', width = 8, font = H_16, underline= 0)
- PopupBtn.pack(side = LEFT, padx = "2m")
- PopupBtn.menu = Menu(PopupBtn)
- PopupBtn.menu.add_command(label = "Segment Registers",font = H_16,command=displaySegments)
- # PopupBtn.menu.add_command(label = "Segment Descriptors",font = H_16,command=displayDescriptors)
- PopupBtn.menu.add_command(label = "Debug Registers",font=H_16,command=displayDebugRegs)
- PopupBtn.menu.add_command(label = "Test Registers",font=H_16,command=displayTestRegs)
- PopupBtn.menu.add_command(label = "Control Registers",font=H_16,command=displayControlRegs)
- PopupBtn['menu'] = PopupBtn.menu
- return PopupBtn
- #
- # Make View Menu
- #
- def displayEIP():
- m = Toplevel(root,width = 200, height = 600)
- m.wm_geometry(Display_Geometry)
- m.title("Stack")
- r = Reg(32)
- def makeViewMenu():
- ViewBtn = Menubutton(mBar, text = 'View', width = 8, font = H_16, underline= 0)
- ViewBtn.pack(side = LEFT, padx = "2m")
- ViewBtn.menu = Menu(ViewBtn)
- ViewBtn.menu.add_command(label = "Stack",font = H_16, command=displayStack)
- ViewBtn.menu.add_command(label = "Show Flags Register",font = H_16, command=displayStack, state = DISABLED)
- ViewBtn.menu.add_command(label = "Current Privilege Level",font = H_16, command=displayStack, state = DISABLED)
- ViewBtn.menu.add_command(label = "Instruction Pointer",font = H_16,command=displaySegments, state = DISABLED)
- ViewBtn['menu'] = ViewBtn.menu
- return ViewBtn
- #
- # Make Settings Menu
- #
- def settabwidth():
- f = Frame(root, width = 200, height = 600)
- f.place(x = 515, y = 40)
- Maximum_choice = 15
- l = Label(f, font = H_16, text = "Spaces per Tab", background = 'white')
- l.pack(side= TOP, fill = X)
- list = Listbox(f,font = H_16, height = Maximum_choice, width = 15, selectmode=SINGLE)
- list.pack(side = TOP)
- for x in range(1, Maximum_choice + 1):
- list.insert(END,str(x))
- list.bind('<Button-1>', lambda e: gettabwidth(e))
- f.bind('<Leave>', lambda e: e.widget.destroy())
- Use_size = IntVar()
- Use_size.set(32)
- def askforpace():
- Choices_list = ['30','60','120','300','600','1200','3000','6000']
- f = Frame(root, width = 200, height = 600)
- f.place(x = 515, y = 40)
- l = Label(f, font = H_16, text = "Instructions per Minute", background = 'white')
- l.pack(side= TOP, fill = X)
- list = Listbox(f,font = H_16,height = len(Choices_list), width = 10,selectmode=SINGLE)
- list.pack(side = TOP)
- for x in Choices_list:
- list.insert(END,str(x))
- list.bind('<Button-1>', lambda e: getpace(e))
- f.bind('<Leave>', lambda e: e.widget.destroy())
- def getpace(e):
- selections = e.widget.curselection()
- if not selections :
- return
- num = int(e.widget.get(selections[0]))
- e.widget.destroy()
- prog.pace= 60000//num
- def gettabwidth(e):
- selections = e.widget.curselection()
- if not selections :
- return
- num = int(e.widget.get(selections[0]))
- e.widget.destroy()
- prog.tabwidth = num
- def trypopup():
- m = Toplevel(root)
- m.title("Trythis")
- def makeOptionsMenu():
- OptionBtn = Menubutton(mBar, text = 'Settings', width = 8, font = H_16, underline = 0)
- OptionBtn.pack(side = LEFT, padx = "2m")
- OptionBtn.menu = Menu(OptionBtn)
- RadBtn = Menubutton(OptionBtn)
- RadBtn.menu = Menu(RadBtn)
- RadBtn.menu.add_radiobutton(label = '32 bit coding', font = H_16,
- value=32, variable= Use_size)
- RadBtn.menu.add_radiobutton(label = '16 bit coding', font = H_16,
- value=16, variable= Use_size)
- OptionBtn.menu.add_command(label = "Run Speed", font = H_16, command = askforpace)
- # OptionBtn.menu.add_command(label = "Load Origin",font = H_16, command = trypopup)
- OptionBtn.menu.add_command(label = "Tab Width",font = H_16, command = settabwidth)
- OptionBtn.menu.add_cascade(label = 'Coding Default', font = H_16, menu = RadBtn.menu)
- OptionBtn['menu'] = OptionBtn.menu
- return OptionBtn
- #
- # Make About Menu
- #
- def showAbout(event):
- s_ver = sys.version_info
- message = Message(root,background = "white",width = 400, font = H_16,
- text="""This program was written by Bob Neveln, with additions by John Stoddart. It supports the textbook `Linux Assembly Language Programming' available from Prentice-Hall. The program implements in Python the C language pseudo-code in Rakesh Agarwal's 80x86 Architecture & Programming, Volume II. Bugs may be reported to neveln@cs.widener.edu""" )
- #text= "Python version " + "%d.%d.%d\n"%(s_ver.major,s_ver.minor,s_ver.micro))
- # message.pack(side = TOP)
- message.place(x=600,y=40)
- message.bind('<Button-1>',lambda e: e.widget.destroy(),'+')
- message.bind('<Leave>',lambda e: e.widget.destroy(),'+')
- def makeAboutMenu():
- AboutBtn = Menubutton(mBar, text = 'About', width = 8, font = H_16, underline= 0)
- AboutBtn.pack(side = LEFT, padx = "2m")
- AboutBtn.bind('<Button-1>', showAbout)
- return AboutBtn
- #
- # Make Help Menu
- #
- def helpKeys():
- key_help = Toplevel()
- key_help.title("Key Commands")
- message = Message(key_help,background = "white", font = H_16, text="""
- C - change a line
- D - delete a line
- I - insert lines
- J - go down a line
- K - go up a line
- P - paste a line
- Q - quit the program
- R - re-open a file""" )
- # message.pack(side = TOP)
- message.grid()
- # message.bind('<Button-1>',lambda e: e.widget.destroy(),'+')
- # message.bind('<Leave>',lambda e: e.widget.destroy(),'+')
- def helpEdit():
- message = Message(root,background = "white",width = 400, font = H_16,
- text="""This program has line-editing capabilities. To edit a line in the center panel, first select it by clicking on it. You may then delete it, change it, or insert another line at that location. Select these functions using the Edit menu and make your edits in the orange lit Enter command box. You may also use an external editor and Re-Open the source file.""" )
- message.place(x=700,y=40)
- message.bind('<Button-1>',lambda e: e.widget.destroy(),'+')
- message.bind('<Leave>',lambda e: e.widget.destroy(),'+')
- def helpRun():
- message = Message(root,background = "white",width = 400, font = H_16,
- text="""Once a program is loaded you may execute single steps that are first selected using the mouse. To do a single step hit the Space Bar. If you need to leave edit mode you may use Single-stepping on the Run menu. To run the program you may either hit Run on the Run menu or select the first instruction and hit Continue. """ )
- message.place(x=700,y=40)
- message.bind('<Button-1>',lambda e: e.widget.destroy(),'+')
- message.bind('<Leave>',lambda e: e.widget.destroy(),'+')
- def makeHelpMenu():
- HelpBtn = Menubutton(mBar, text = 'Help', width = 8, font = H_16, underline= 0)
- HelpBtn.pack(side = LEFT, padx = "2m")
- HelpBtn.menu = Menu(HelpBtn)
- HelpBtn.menu.add_command(label = "Help Edit",font = H_16,command=helpEdit)
- HelpBtn.menu.add_command(label = "Help Run",font = H_16,command=helpRun)
- HelpBtn.menu.add_command(label = "Help Keys",font = H_16,command=helpKeys)
- HelpBtn['menu'] = HelpBtn.menu
- return HelpBtn
- FileBtn = makeFileMenu()
- EditBtn = makeEditMenu()
- RunBtn = makeRunMenu()
- RunBtn.configure(state = DISABLED)
- InternalsBtn = makePopupMenu()
- ViewBtn = makeViewMenu()
- OptionBtn = makeOptionsMenu()
- AboutBtn = makeAboutMenu()
- HelpBtn = makeHelpMenu()
- #mBar.tk_menuBar(FileBtn,EditBtn,RunBtn,InternalsBtn,ViewBtn,OptionBtn,AboutBtn,HelpBtn)
- #############################################################################
- #
- # End Menu Section
- #
- #############################################################################
- #
- # The following code used for the codePanel was taken from
- #
- # tkinter.unpy.net/wiki
- #
- class VerticalScrolledFrame(Frame):
- def __init__(self, parent, *args, **kw):
- Frame.__init__(self,parent,*args,**kw)
- vscrollbar = Scrollbar(self, orient=VERTICAL)
- vscrollbar.pack(fill=Y,side=RIGHT,expand=FALSE)
- canvas = Canvas(self, height=510,bd=0,highlightthickness=0,yscrollcommand=vscrollbar.set)
- canvas.pack(side=LEFT,fill=BOTH,expand=TRUE)
- vscrollbar.config(command=canvas.yview)
- canvas.xview_moveto(0)
- canvas.yview_moveto(0)
- self.interior = interior = Frame(canvas)
- interior_id = canvas.create_window(0,0,window=interior,anchor=NW)
- def _configure_interior(event):
- size = (interior.winfo_reqwidth(),interior.winfo_reqheight())
- canvas.config(scrollregion="0 0 %s %s" % size)
- if interior.winfo_reqwidth() != canvas.winfo_width():
- canvas.config(width = interior.winfo_reqwidth())
- interior.bind('<Configure>', _configure_interior)
- def _configure_canvas(event):
- if interior.winfo_reqwidth() != canvas.winfo_width():
- canvas.itemconfigure(interior_id,width=canvas.winfo_width())
- canvas.bind('<Configure>', _configure_canvas)
- return
- #############################################################################
- #
- # This is the center panel containing the source code:
- #
- #############################################################################
- codePanel = VerticalScrolledFrame(root,width = 440, height = 510, background = "white")
- codePanel.place(x = 400,y = 85)
- m = Frame(codePanel.interior,borderwidth=0,
- width = 340,
- background = "white")
- m.pack(side = TOP, fill = X, expand = YES)
- #############################################################################
- #
- # This is the memory viewing window:
- #
- #############################################################################
- memoryPanel = Frame(root,width = 200, height = 540, background = "white")
- memoryPanel.place(x = 820,y = 85)
- # Initialize memory with zeros
- addr_bits = 20
- mem = Memory(addr_bits, memoryPanel)
- mem.viewbase = 0
- mem.refresh()
- # Initialize the base setting Window
- lbl = Label(root, background = "red",
- foreground = "yellow",
- text = "Memory Base:" ,
- width = 13,
- font = "Arial 16")
- lbl.place(x = 830, y = 44)
- MemBaseBox = build_membox(root)
- MemBaseBox.bind("<Return>", set_viewbase)
- # Title the screen with the CPU type
- proc_name = Label(root, text = "486 CPU",
- background = "blue",
- foreground = "yellow",
- width = 15,
- font = "Arial 24")
- proc_name.place(x = 436,y = 40)
- #
- # Create the registers and the flags
- #
- archnum = 4 # only 486 for now
- register_names = ["EAX","EBX","ECX","EDX","ESP","EBP","ESI","EDI"]
- genReg = []
- y_coord = 70
- for r_name in register_names:
- reg = Modifiable_Register(r_name,32)
- genReg.append(reg)
- reg.place(x = 5, y = y_coord)
- reg.bind("<Return>", reg.quit)
- y_coord = y_coord + 60
- reg_ebx = genReg[1]
- del genReg[1]
- genReg[3:3] = [reg_ebx]
- flag_names = ["CF","OF","ZF","SF"]
- Flags = {}
- x_coord = 7
- y_coord = 560
- for f_name in flag_names:
- flag = Flag(f_name)
- Flags[f_name] = flag
- flag.place(x = x_coord,y=y_coord)
- x_coord = x_coord + 75
- if x_coord > 240:
- x_coord = 7
- y_coord = y_coord + 40
- flag_names = ["AF","PF","DF","IF","TF","NT","RF","VM","AC"]
- for f_name in flag_names:
- flag = Flag(f_name)
- Flags[f_name] = flag
- EIP = InstructionPointer(32)
- #
- # Segment Register and Descriptor Table Numbers
- #
- register_names = ["ES","CS","SS","DS","FS","GS","LDTS","TSS"]
- segReg = []
- for r_name in register_names:
- sreg = Viewable_Register(16, r_name)
- sreg.strvalue.set(" " + "".join(random.sample("0123456789ABCDEF",4)))
- segReg.append(sreg)
- ES = 0
- CS = 1
- SS = 2
- DS = 3
- FS = 4
- GS = 5
- LDT = 6
- TSS = 7
- GDT = 8
- IDT = 9
- descrVec = [Descr() for i in range(10)]
- debReg = []
- for n in range(8):
- ireg = Viewable_Register(32, "DR" + str(n))
- debReg.append(ireg)
- testReg = []
- for n in range(8):
- ireg = Viewable_Register(32, "TR" + str(n))
- testReg.append(ireg)
- ctrlReg = []
- for n in range(4):
- ireg = Viewable_Register(32, "CR" + str(n))
- ctrlReg.append(ireg)
- #
- # Create the flags register
- #
- #
- CPL = 0
- IOPL = Viewable_Register(2, "IOPL")
- class Signal:
- def __init__(self):
- self.input_register = 0 # Used by IN handler to distinguish AL, AX, EAX
- self.pending_repeat = ''
- signal = Signal()
- #
- # Create the User Entry Box Below the Registers and the Code Panel
- #
- User_Entry = Frame(root, height=8,width=80)
- User_Entry.place(x = 5, y = 620)
- userbox_label = Label(User_Entry, background = "green",
- foreground = "black",
- text = "Enter Command:",
- width = 15,
- font = "Arial 20")
- userbox_label.pack(side = LEFT)
- userbox_label.bind('<Button-1>', interpret)
- entrybox_contents = StringVar()
- entrybox=Entry(User_Entry, relief=SUNKEN,
- textvariable=entrybox_contents,
- width = 32,
- background = "white",
- font = "Arial 20")
- def getEntry(event,d=entrybox_contents):
- user_entry = d.get()
- d.set('')
- if prog.execstate == 'stepping':
- return
- elif prog.execstate == 'running':
- return
- elif prog.execstate == 'blocked':
- input_data(user_entry)
- elif prog.execstate in ['interpreting', 'inserting','changing']:
- if user_entry.strip() == '':
- prog.set_execstate('stepping')
- return
- line = build_line(user_entry)
- if type(line) is str:
- print_feedback(line)
- return
- if prog.execstate == 'inserting':
- prog.instinsert(line)
- prog.store()
- prog.refresh()
- # prog.set_current_inst(instnum = prog.current_inst) # New code
- if prog.current_inst == len(prog.codelist)-1:
- pass
- else:
- prog.set_current_inst(instnum = prog.current_inst )
- mem.refresh()
- elif prog.execstate == 'changing':
- prog.instdelete()
- prog.instinsert(line)
- mem.refresh()
- prog.set_execstate('stepping')
- prog.refresh()
- else:
- if line.hexcode == '':
- print_feedback("Unknown command: ")
- return
- prog.stored_command = line.hexcode
- prog.execstack.append(user_entry)
- prog.execstackpointer = 0
- save_EIP = EIP.getvalue()
- EIP.setvalue(prog.store_origin)
- try:
- fetchexec()
- except x86exception as e:
- print_feedback("Exception "+str(e.interrupt_number)+': '+ e.error_message+ ' ')
- EIP.setvalue(save_EIP)
- prog.set_current_inst(instoffset = save_EIP)
- def space_off(event):
- root.unbind('<KeyPress-space>')
- def space_on(event):
- root.bind('<KeyPress-space>', spacebar_handle)
- entrybox.pack(side=LEFT,expand=YES,fill=BOTH)
- entrybox.bind("<Return>", getEntry)
- entrybox.bind("<Enter>", space_off, '+')
- entrybox.bind("<Leave>", space_on, '+')
- #
- # Create the Feedback Window at the Bottom of the Screen
- #
- Feedback_Box = Entry(root, width=80,
- font = "Arial 20",
- disabledforeground="black",
- disabledbackground ="white",
- state="disabled")
- Feedback_Box.place(x = 5, y = 670)
- def print_feedback(text, delete = False):
- Feedback_Box["state"]="normal"
- if delete:
- Feedback_Box.delete(0,END)
- Feedback_Box.insert(0, text)
- Feedback_Box["state"]="disabled"
- def print_output(text):
- global Data_Box
- try:
- Data_Box.insert(END, text + '\n')
- except:
- m = Toplevel(root,width = 100, height = 590)
- m.wm_geometry(Display_Geometry)
- m.title("Program Output")
- m.wm_attributes("-topmost", 1)
- Data_Box = Text(m,width = 20,height = 100,font = "Arial 20", state = "normal")
- Data_Box.pack(side = TOP)
- Data_Box.insert(END, text + '\n')
- #
- # Add Key Bindings
- #
- def key_Down_handle(event):
- if prog.execstate == 'stepping' or prog.execstate == 'inserting':
- if prog.current_inst == len(prog.codelist)-1:
- pass
- else:
- prog.set_current_inst(instnum = prog.current_inst )
- elif prog.execstate == 'interpreting':
- if prog.execstackpointer < 0:
- prog.execstackpointer = prog.execstackpointer + 1
- if prog.execstackpointer < 0:
- entrybox_contents.set(prog.execstack[prog.execstackpointer])
- elif prog.execstackpointer == 0:
- entrybox_contents.set(' ')
- def key_Up_handle(event):
- if prog.execstate == 'stepping' or prog.execstate == 'inserting':
- if prog.current_inst == 1:
- pass
- else:
- prog.set_current_inst(instnum = prog.current_inst -2)
- elif prog.execstate == 'interpreting':
- if - prog.execstackpointer < len(prog.execstack):
- prog.execstackpointer = prog.execstackpointer - 1
- entrybox_contents.set(prog.execstack[prog.execstackpointer])
- def key_c_handle(event):
- if prog.execstate == 'stepping':
- changeline()
- def key_d_handle(event):
- if prog.execstate == 'stepping':
- delete_current()
- def key_i_handle(event):
- if prog.execstate == 'stepping':
- insert_mode()
- def key_j_handle(event):
- if prog.execstate == 'stepping' or prog.execstate == 'inserting':
- if prog.current_inst == len(prog.codelist)-1:
- pass
- else:
- prog.set_current_inst(instnum = prog.current_inst )
- def key_k_handle(event):
- if prog.execstate == 'stepping' or prog.execstate == 'inserting':
- if prog.current_inst == 1:
- pass
- else:
- prog.set_current_inst(instnum = prog.current_inst -2)
- def key_p_handle(event):
- if prog.execstate == 'stepping':
- insert_saved_line()
- def key_q_handle(event):
- if prog.execstate == 'stepping':
- FileBtn.quit()
- def key_r_handle(event):
- if prog.execstate == 'stepping':
- open_same_file()
- def do_nothing(e=None):
- pass
- def spacebar_handle(event):
- if prog.execstate == 'stepping':
- try:
- fetchexec()
- except x86exception as e:
- print_feedback("Exception "+str(e.interrupt_number)+': '+ e.error_message + ' ')
- def key_y_handle(event):
- print_feedback("current_inst = " + str(prog.current_inst))
- print_feedback("EIP = " + str(EIP.getvalue()))
- root.bind('<KeyRelease-F5>', continue_execution)
- root.bind('<KeyPress-c>', key_c_handle)
- root.bind('<KeyPress-d>', key_d_handle)
- root.bind('<KeyPress-i>', key_i_handle)
- root.bind('<KeyPress-j>', key_j_handle)
- root.bind('<KeyPress-k>', key_k_handle)
- root.bind('<KeyPress-p>', key_p_handle)
- root.bind('<KeyPress-q>', key_q_handle)
- root.bind('<KeyPress-r>', key_r_handle)
- root.bind('<KeyPress-y>', key_y_handle)
- root.bind('<KeyPress-Down>', key_Down_handle)
- root.bind('<KeyPress-Up>', key_Up_handle)
- root.bind('<KeyPress-space>',spacebar_handle)
- root.bind('<KeyPress-Tab>', do_nothing)
- #
- # Start with a command line program if there is one
- #
- prog = Program()
- prog.refresh()
- if len(sys.argv) > 1:
- if os.path.isfile(sys.argv[1]):
- open_file(sys.argv[1])
- prog.filename = sys.argv[1]
- else:
- print_feedback("Couldn't find file: " + sys.argv[1])
- prog.set_execstate('interpreting')
- else:
- prog.set_execstate('interpreting')
- root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement