node/lib/metasm/metasm/cpu/ia32/decode.rb
# tries to find the opcode encoded at edata.ptr
# if no match, tries to match a prefix (update di.instruction.prefix)
# on match, edata.ptr points to the first byte of the opcode (after prefixes)
tries to find the opcode encoded at edata.ptr
if no match, tries to match a prefix (update di.instruction.prefix)
on match, edata.ptr points to the first byte of the opcode (after prefixes)
tries to find the opcode encoded at edata . ptr if no match tries to match a prefix ( update di . instruction . prefix ) on match edata . ptr points to the first byte of the opcode ( after prefixes )
def decode_findopcode(edata)
		di = DecodedInstruction.new self
		while edata.ptr < edata.data.length
			pfx = di.instruction.prefix || {}
			byte = edata.data[edata.ptr]
			byte = byte.unpack('C').first if byte.kind_of?(::String)
			return di if di.opcode = @bin_lookaside[byte].find { |op|
				bseq = edata.data[edata.ptr, op.bin.length].unpack('C*')
				op.bin.zip(bseq, op.bin_mask).all? { |b1, b2, m| b2 and ((b1 & m) == (b2 & m)) } and
				!(
				  (fld = op.fields[:seg2A]  and (bseq[fld[0]] >> fld[1]) & @fields_mask[:seg2A] == 1) or
				  (fld = op.fields[:seg3A]  and (bseq[fld[0]] >> fld[1]) & @fields_mask[:seg3A] < 4) or
				  (fld = op.fields[:seg3A] || op.fields[:seg3] and (bseq[fld[0]] >> fld[1]) & @fields_mask[:seg3] > 5) or
				  (op.props[:modrmA] and fld = op.fields[:modrm] and (bseq[fld[0]] >> fld[1]) & 0xC0 == 0xC0) or
				  (op.props[:modrmR] and fld = op.fields[:modrm] and (bseq[fld[0]] >> fld[1]) & 0xC0 != 0xC0) or
				  (fld = op.fields[:vex_vvvv] and @size != 64 and (bseq[fld[0]] >> fld[1]) & @fields_mask[:vex_vvvv] < 8) or
				  (sz = op.props[:opsz] and opsz(di, op) != sz) or
				  (sz = op.props[:adsz] and adsz(di, op) != sz) or
				  (ndpfx = op.props[:needpfx] and not pfx[:list].to_a.include? ndpfx) or
				  (pfx[:adsz] and op.props[:adsz] and op.props[:adsz] == @size) or
				  (pfx[:opsz] and not op.props[:opsz] and (op.args == [:i] or op.args == [:farptr] or op.name == 'ret')) or
				  (pfx[:adsz] and not op.props[:adsz] and (op.props[:strop] or op.props[:stropz] or op.args.include?(:mrm_imm) or op.args.include?(:modrm) or op.name =~ /loop|xlat/)) or
				  (op.name == 'nop' and op.bin[0] == 0x90 and di.instruction.prefix and di.instruction.prefix[:rex_b])
				 )
			}
			break if not decode_prefix(di.instruction, edata.get_byte)
			di.bin_length += 1
		end
	end
def decode_findopcode ( edata ) di = DecodedInstruction . new self while edata . ptr < edata . data . length pfx = di . instruction . prefix || { } byte = edata . data [ edata . ptr ] byte = byte . unpack ( 'C' ) . first if byte . kind_of? ( :: String ) return di if di . opcode = @bin_lookaside [ byte ] . find { | op | bseq = edata . data [ edata . ptr , op . bin . length ] . unpack ( 'C*' ) op . bin . zip ( bseq , op . bin_mask ) . all? { | b1 , b2 , m | b2 and ( ( b1 & m ) == ( b2 & m ) ) } and ! ( ( fld = op . fields [ :seg2A ] and ( bseq [ fld [ 0 ] ] >> fld [ 1 ] ) & @fields_mask [ :seg2A ] == 1 ) or ( fld = op . fields [ :seg3A ] and ( bseq [ fld [ 0 ] ] >> fld [ 1 ] ) & @fields_mask [ :seg3A ] < 4 ) or ( fld = op . fields [ :seg3A ] || op . fields [ :seg3 ] and ( bseq [ fld [ 0 ] ] >> fld [ 1 ] ) & @fields_mask [ :seg3 ] > 5 ) or ( op . props [ :modrmA ] and fld = op . fields [ :modrm ] and ( bseq [ fld [ 0 ] ] >> fld [ 1 ] ) & 0xC0 == 0xC0 ) or ( op . props [ :modrmR ] and fld = op . fields [ :modrm ] and ( bseq [ fld [ 0 ] ] >> fld [ 1 ] ) & 0xC0 != 0xC0 ) or ( fld = op . fields [ :vex_vvvv ] and @size != 64 and ( bseq [ fld [ 0 ] ] >> fld [ 1 ] ) & @fields_mask [ :vex_vvvv ] < 8 ) or ( sz = op . props [ :opsz ] and opsz ( di , op ) != sz ) or ( sz = op . props [ :adsz ] and adsz ( di , op ) != sz ) or ( ndpfx = op . props [ :needpfx ] and not pfx [ :list ] . to_a . include? ndpfx ) or ( pfx [ :adsz ] and op . props [ :adsz ] and op . props [ :adsz ] == @size ) or ( pfx [ :opsz ] and not op . props [ :opsz ] and ( op . args == [ :i ] or op . args == [ :farptr ] or op . name == 'ret' ) ) or ( pfx [ :adsz ] and not op . props [ :adsz ] and ( op . props [ :strop ] or op . props [ :stropz ] or op . args . include? ( :mrm_imm ) or op . args . include? ( :modrm ) or op . name =~ / loop|xlat / ) ) or ( op . name == 'nop' and op . bin [ 0 ] == 0x90 and di . instruction . prefix and di . instruction . prefix [ :rex_b ] ) ) } break if not decode_prefix ( di . instruction , edata . get_byte ) di . bin_length += 1 end end
tries to find the opcode encoded at edata.ptr
if no match, tries to match a prefix (update di.instruction.prefix)
on match, edata.ptr points to the first byte of the opcode (after prefixes)
tries to find the opcode encoded at edata . ptr if no match tries to match a prefix ( update di . instruction . prefix ) on match edata . ptr points to the first byte of the opcode ( after prefixes )
# fetch the relevant bytes from edata # check against full opcode mask # check special cases # fail if any of those is true # return non-ambiguous opcode (eg push.i16 in 32bit mode) / sync with addop_post in opcode.rb
edata