#cd [file dirname [currentFileGet]] if 0 { set v 0xa7 set size 1 if { $v& (1<<(($size<<3)-1)) } { incr v [expr -1- ((1<<($size<<3))-1)] } puts stdout [format 0x%08lx $v] return } namespace eval i386 { set instructions { 0x00 bitrm 0x01 bitrm 0x02 bitrm 0x03 bitrm 0x04 bitrm 0x05 bitrm 0x06 push 0x07 pop 0x08 bitrm 0x09 bitrm 0x0a bitrm 0x0b bitrm 0x0c bitrm 0x0d bitrm 0x0e push 0x0f x0f 0x10 bitrm 0x11 bitrm 0x12 bitrm 0x13 bitrm 0x14 bitrm 0x15 bitrm 0x16 push 0x17 pop 0x18 bitrm 0x19 bitrm 0x1a bitrm 0x1b bitrm 0x1c bitrm 0x1d bitrm 0x1e push 0x1f pop 0x20 bitrm 0x21 bitrm 0x22 bitrm 0x23 bitrm 0x24 bitrm 0x25 bitrm 0x26 "preSeg es" 0x27 daa 0x28 bitrm 0x29 bitrm 0x2a bitrm 0x2b bitrm 0x2c bitrm 0x2d bitrm 0x2e "preSeg cs" 0x2f das 0x30 bitrm 0x31 bitrm 0x32 bitrm 0x33 bitrm 0x34 bitrm 0x35 bitrm 0x36 "preSeg ss" 0x37 aaa 0x38 bitrm 0x39 bitrm 0x3a bitrm 0x3b bitrm 0x3c bitrm 0x3d bitrm 0x3e "preSeg ds" 0x3f aas 0x40 inc 0x41 inc 0x42 inc 0x43 inc 0x44 inc 0x45 inc 0x46 inc 0x47 inc 0x48 dec 0x49 dec 0x4a dec 0x4b dec 0x4c dec 0x4d dec 0x4e dec 0x4f dec 0x50 push 0x51 push 0x52 push 0x53 push 0x54 push 0x55 push 0x56 push 0x57 push 0x58 pop 0x59 pop 0x5a pop 0x5b pop 0x5c pop 0x5d pop 0x5e pop 0x5f pop 0x60 push 0x61 pop 0x62 bound 0x63 arpl 0x64 "preSeg fs" 0x65 "preSeg gs" 0x66 "preSize Op" 0x67 "preSize Ad" 0x68 push 0x69 imul 0x6a push 0x6b imul 0x6c ios 0x6d ios 0x6e ios 0x6f ios 0x70 jcc 0x71 jcc 0x72 jcc 0x73 jcc 0x74 jcc 0x75 jcc 0x76 jcc 0x77 jcc 0x78 jcc 0x79 jcc 0x7a jcc 0x7b jcc 0x7c jcc 0x7d jcc 0x7e jcc 0x7f jcc 0x80 bitrm 0x81 bitrm 0x82 bitrm 0x83 bitrm 0x84 test 0x85 test 0x86 xchg 0x87 xchg 0x88 mov 0x89 mov 0x8a mov 0x8b mov 0x8c mov 0x8d lea 0x8e mov 0x8f pop 0x90 nop 0x91 xchg 0x92 xchg 0x93 xchg 0x94 xchg 0x95 xchg 0x96 xchg 0x97 xchg 0x98 cbw 0x99 cdq 0x9a call 0x9b wait 0x9c pushf 0x9d popf 0x9e sahf 0x9f lahf 0xa0 mov 0xa1 mov 0xa2 mov 0xa3 mov 0xa4 movs 0xa5 movs 0xa6 cmps 0xa7 cmps 0xa8 test 0xa9 test 0xaa stos 0xab stos 0xac lods 0xad lods 0xae scas 0xaf scas 0xb0 mov 0xb1 mov 0xb2 mov 0xb3 mov 0xb4 mov 0xb5 mov 0xb6 mov 0xb7 mov 0xb8 mov 0xb9 mov 0xba mov 0xbb mov 0xbc mov 0xbd mov 0xbe mov 0xbf mov 0xc0 rotation 0xc1 rotation 0xc2 ret 0xc3 ret 0xc4 les 0xc5 lds 0xc6 mov 0xc7 mov 0xc8 enter 0xc9 leave 0xca ret 0xcb ret 0xcc int 0xcd int 0xce int 0xcf iret 0xd0 rotation 0xd1 rotation 0xd2 rotation 0xd3 rotation 0xd4 aam 0xd5 aad 0xd6 tbd 0xd7 xlat 0xd8 tbd 0xd9 tbd 0xda tbd 0xdb tbd 0xdc tbd 0xdd tbd 0xde tbd 0xdf tbd 0xe0 loop 0xe1 loop 0xe2 loop 0xe3 jcxz 0xe4 io 0xe5 io 0xe6 io 0xe7 io 0xe8 call 0xe9 jmp 0xea jmp 0xeb jmp 0xec io 0xed io 0xee io 0xef io 0xf0 lock 0xf1 xf1 0xf2 repne 0xf3 repe 0xf4 hlt 0xf5 cmc 0xf6 xf6 0xf7 xf6 0xf8 clc 0xf9 stc 0xfa cli 0xfb sti 0xfc cld 0xfd std 0xfe xfe 0xff xfe } foreach { i name } $instructions { set i [expr $i] set names($i) $name } proc share {} { uplevel { variable byte variable bin variable pc variable todos variable dones variable names variable model variable bytes variable address variable pre variable lock variable swapSizeAd variable swapSizeOp variable bin_offset variable bin_mask } } for {set i 0} {$i<8} {incr i} { set ::log2([expr 1<<$i]) $i } proc puts { text } { share global reverse set text [format "/* 0x%08lx %-20s */ %s" $address [join $bytes " "] $text] #::puts stdout $text lappend reverse $text } proc next {} { share set offset [expr ($pc-$bin_offset)&$bin_mask] if { [binary scan $bin @[expr $offset]c1 byte]==0 } { error [format "out of data @0x%08lx" $pc] } set byte [expr $byte&0xff] #::puts stdout [format "%08lx %02x" $offset $byte] lappend bytes [format "%02x" $byte] incr pc return $byte } proc immediate { size } { share set v 0 set size [expr 1<<$size] for {set i 0} {$i<$size} {incr i} { incr v [expr [next]<<($i<<3)] } set v } proc sign_extend { v size } { set size [expr 1<<$size] if { $v& (1<<(($size<<3)-1)) } { incr v [expr -1- ((1<<($size<<3))-1)] } set v } proc trunc { v size } { expr $v & ((1<<((1<<$size)<<3))-1) } proc immediatef { from {to -1} } { share if { $to==-1 } { set to $from } format 0x%0[expr (1<<$to)<<1]x [trunc [sign_extend [immediate $from] $from] $to] } proc tbd {} { share error tbd return 0 } proc reg { reg size {pre %}} { return $pre[lindex [lindex { { al cl dl bl ah ch dh bh} { ax cx dx bx sp bp si di} {eax ecx edx ebx esp ebp esi edi} } $size ] $reg] } proc sreg3 { reg {pre %}} { return $pre[lindex { es cs ss ds fs gs ? ?} $reg] } proc sreg2 { reg {pre %}} { if { $reg>=4 } return ? return $pre[sreg3 $reg] } proc modrm { mod rm {w 1} } { if { $mod==3 } { return [reg $rm [sizeOp $w]] } set is32 [expr [sizeAd]-1] set fmt [lindex [lindex [lindex { { { (%bx+%si) (%bx+%di) (%bp+%si) (%bp+%di) (%si) (%di) (dis) (%bx) } { (%bx+%si+dis) (%bx+%di+dis) (%bp+%si+dis) (%bp+%di+dis) (%si+dis) (%di+dis) (%bp+dis) (%bx+dis) } { (%bx+%si+dis) (%bx+%di+dis) (%bp+%si+dis) (%bp+%di+dis) (%si+dis) (%di+dis) (%bp+dis) (%bx+dis) } } { { (%eax) (%ecx) (%edx) (%ebx) s-i-b (dis) (%esi) (%edi) } { (%eax+dis) (%ecx+dis) (%edx+dis) (%ebx+dis) s-i-b (%ebp+dis) (%esi+dis) (%edi+dis) } { (%eax+dis) (%ecx+dis) (%edx+dis) (%ebx+dis) s-i-b (%ebp+dis) (%esi+dis) (%edi+dis) } } } $is32 ] $mod ] $rm] set displacement "" if { $mod || ($rm == ($is32 ? 5:6)) } { set size [expr $mod==1 ? 0:[sizeAd]] regsub dis $fmt [immediatef $size] fmt } return $fmt } proc sizeOp { {w 1} } { share return [expr ($w ? ($::log2([expr $model/16])^$swapSizeOp)+1:0)] } proc sizeAd { {w 1} } { share return [expr ($w ? ($::log2([expr $model/16])^$swapSizeAd)+1:0)] } ###################################### proc x0f {} { share next if { $byte==0x01 } { next set mod [expr ($byte>>6)&3] set reg [expr ($byte>>3)&7] set rm [expr ($byte )&7] if { $reg==0x02 } { puts "lgdt [modrm $mod $rm]" return 1 } if { $reg==0x03 } { puts "lidt [modrm $mod $rm]" return 1 } error } if { $byte==0x08 } { puts "invd" return 1 } if { $byte==0x09 } { puts "wbinvd" return 1 } if { $byte==0xa1 } { puts "pop fs" return 1 } if { $byte==0xa9 } { puts "pop gs" return 1 } if { ($byte&0xf0)==0x80 } { return [jcc 1] } if { $byte==0xab || $byte==0xbb } { if { $byte==0xab } { set type bts } { set type btc } next set mod [expr ($byte>>6)&3] set reg [expr ($byte>>3)&7] set rm [expr ($byte )&7] puts "$type [modrm $mod $rm]" return 1 } if { 0xc8<=$byte && $byte<0xd0 } { puts "bswap [reg [expr $byte & 7] 2]" return 1 } if { $byte==0xbc || $byte==0xbd } { if { $byte==0xbc } { set type bsf } { set type bsr } next set mod [expr ($byte>>6)&3] set reg [expr ($byte>>3)&7] set rm [expr ($byte )&7] puts "$type [modrm $mod $rm]" return 1 } if { $byte==0xb2 || $byte==0xb4 || $byte==0xb5 } { return [les [expr $byte&7]] } if { ($byte&0xf6)==0xb6 } { set signed [expr ($byte>>3)&1] set w [expr ($byte )&1] next set mod [expr ($byte>>6)&3] set reg [expr ($byte>>3)&7] set rm [expr ($byte )&7] puts [format "mov%sx %s,%s" [lindex {s z} $signed] [modrm $mod $rm $w] [reg $reg 1]] return 1 } if { ($byte&0xf8)==0x20 } { set write [expr ($byte>>1)&1] set type [expr (($byte>>1)&2) |($byte&1)] next set eee [expr ($byte>>3)&7] set reg [expr $byte&7] set eee %[lindex [lindex { {CR0 ? CR2 CR3 ? ? ? ? } {DR0 DR1 DR2 DR3 ? ? DR6 DR7} {? ? ? TR3 TR4 TR5 TR6 TR7} } $type] $eee] if { $write } { puts "mov [reg $reg 2],$eee" } { puts "mov $eee,[reg $reg 2]" } return 1 } error x0f } proc xf1 {} { share puts "xf1 !!!" return 1 } proc xf6 {} { share set w [expr $byte&1] next set mod [expr ($byte>>6)&3] set mid [expr ($byte>>3)&7] set rm [expr ($byte )&7] set op [lindex {test ??? not neg mul imul div idiv} $mid] if { $mid==0 } { set v [immediatef [sizeOp $w]] puts [format "%s %s,%s" $op [modrm $mod $rm $w] $v] return 1 } #if { $mid==0} { # puts [format "%s %s" $op [modrm $mod $rm $w]] # return 1 #} if { $mid>=4 } { puts [format "%s %s,%s" $op [reg 0 [sizeOp $w]] [modrm $mod $rm $w]] return 1 } return 1 } proc xfe {} { share set w [expr ($byte )&1] next set mod [expr ($byte>>6)&3] set mid [expr ($byte>>3)&7] set rm [expr ($byte )&7] if { $mid==0 } { return [inc 1 $mod $rm $w] } if { $mid==1 } { return [dec 1 $mod $rm $w] } if { $w } { if { ($mid&6)==2 } { puts "call [expr $mid&6] [modrm $mod $rm 1]" return 1 } if { ($mid&6)==4 } { return [jmp $mid $mod $rm] } if { $mid==6 } { puts "push [modrm $mod $rm 1]" return 1 } error xff } { error xfe } } proc bitrm {} { share set w [expr ($byte )&1] set s [expr ($byte>>1)&1] set type [expr ($byte>>1)&3] set first $byte if { $type!=2 } { next set mod [expr ($byte>>6)&3] set reg [expr ($byte>>3)&7] set rm [expr ($byte )&7] } if { ($first&0xfc)==0x80 } { set op [expr ($byte>>3)&7] } { set op [expr ($first>>3)&7] } set op [lindex {add or adc sbb and sub xor cmp} $op] if { $type==2 } { # immediatef to accumulator set size [sizeOp $w] set v [immediatef $size] puts [format {%s %s,$%s} $op [reg 0 $size] $v] return 1 } if { ($first&0xfc)==0x80} { # immediatef to r/m set rm [modrm $mod $rm $w] if { $s } { set v [immediatef 0 [sizeOp $w]] } { set v [immediatef [sizeOp $w]] } puts [format {%s %s,$%s} $op $rm $v] return 1 } #RegistertoRegister 1 [00dw ][11 reg r/m ] #Register to Memory 1 [000w ][mod reg r/m ] #Memory to Register 1 [001w ][mod reg r/m ] #Immediate to Register/Memory 8 [00sw ][mod 010 r/m ] # #Immediate to Accumulator 1 [010w ] # #if { ($first&0x04)==0x00 && ($byte&0xc0)==0xc0 } set d [expr ($first>>1)&1] set size [sizeOp $w] set reg [reg $reg $size] set mem [modrm $mod $rm $w] if { $d } { puts [format {%s %s,%s} $op $reg $mem] } { puts [format {%s %s,%s} $op $mem $reg] } return 1 } proc aad {} { share puts "aad [immediatef 0]" return 1 } proc aam {} { share puts "aam [immediatef 0]" return 1 } proc call {} { share if { $byte==0xe8 } { set rel [sign_extend [immediate [sizeAd]] [sizeAd]] incr rel $pc puts [format "call 0x%08x" $rel] lappend todos $rel } { # 0x9a set seg [immediatef 1] set off [immediatef [sizeAd] 2] puts "call $seg:$op" } return 1 } proc cbw {} { share puts [format "%s" [lindex {"" cbw cwde} [sizeOp]]] return 1 } proc cdq {} { share puts [lindex {"" "cwd" "cdq"} [sizeOp]] return 1 } proc clc {} { share puts [format "clc"] return 1 } proc cld {} { share puts [format "cld"] return 1 } proc cli {} { share puts [format "cli"] return 1 } proc cmps {} { share puts "cmps[lindex {b w d} [sizeOp ($byte&1)]]" return 1 } proc dec { {modrm 0} {mod 0} {rm 0} {w 0} } { share return [inc $modrm $mod $rm $w 1] } proc daa {} { puts daa return 1 } proc das {} { puts daa return 1 } proc hlt {} { puts hlt return 1 } proc inc { {modrm 0} {mod 0} {rm 0} {w 0} {dec 0} } { share if { $modrm } { set v [modrm $mod $rm $w] } { set v [reg [expr $byte&7] [sizeOp]] } puts [format "%s %s" [lindex {inc dec} $dec] $v] return 1 } proc imul {} { share set w [expr ($byte>>1)&1] next set mod [expr ($byte>>6)&3] set reg [expr ($byte>>3)&7] set rm [expr ($byte )&7] set imm [immediatef [sizeOp $w]] puts "imul [modrm $mod $rm $w] $imm" return 1 } proc int {} { share if { $byte==0xcc } { puts "int 3" } { if { $byte==0xcd } { puts "int [immediatef 0]" } { puts "into" } } return 1 } proc io {} { share set first $byte set w [expr $first&1] #puts [format "%d 0x%02x" $w $byte] set size [sizeOp $w] if { $first&0x08 } { set ad "%dx" } { set ad $[immediatef 0] } if { $first&2 } { puts [format {out %s,%s} [reg 0 $size] $ad] } { puts [format {in %s,%s} $ad [reg 0 $size]] } return 1 } proc ios {} { share set first $byte set w [expr $byte&1] set size [sizeOp $w] if { $byte&2 } { puts [format {outs %s,%s} %dx %ds:%si] } { puts [format {ins %s,%s} %ds:%si %dx] } return 1 } proc iret {} { share puts iret return 1 } proc jcc { {near 0} } { share set type [expr $byte&0xf] set type [lindex {"" "n"} [expr $type&1]][lindex {o c e be s p l le} [expr ($type>>1)&7]] set size 0 if { $near } { set size [sizeAd] } set rel [sign_extend [immediate $size] $size] incr rel $pc puts [format "j%s 0x%08x" $type $rel] lappend todos $rel return 1 } proc jcxz { } { share set rel [immediatef 0 2] incr rel $pc puts [format "j%sz 0x%08x" [reg 1 [sizeOp] ""] $rel] lappend todos $rel return 1 } proc jmp { {mid 0} {mod ""} {rm ""} } { share set continue 1 if { $mid==4 } { puts [format "jmp %s" [modrm $mod $rm]] return $continue } if { $mid==5 } { puts [format "jmp %s" [modrm $mod $rm]] return $continue } if { $byte==0xe9 } { set rel [immediatef 1] set rel [expr ($pc&0xffff0000)|($pc+$rel)&0xffff] #if { $rel&0x8000 } { # incr rel 0xffff0000 #} #incr rel $pc puts [format "jmp 0x%08x" $rel] lappend todos $rel return $continue } if { $byte==0xea } { set offset [immediatef [sizeAd]] set seg [immediatef 1] #set add [expr ($seg<<4)+$offset] set add [expr $offset] puts [format "jmp %s:%s (0x%08lx)" $offset $seg $add] lappend todos $add return $continue } if { $byte==0xeb } { set rel [immediatef 0] if { $rel&0x80 } { incr rel 0xffffff00 } incr rel $pc puts [format "jmp 0x%08x" $rel] lappend todos $rel return $continue } error jmp } proc lahf {} { share puts lahf return 1 } proc lea {} { share next set mod [expr ($byte>>6)&3] set reg [expr ($byte>>3)&7] set rm [expr ($byte )&7] puts "lea [reg $reg [sizeOp]] [modrm $mod $rm]" return 1 } proc les { {type 0}} { share next set reg [expr ($byte>>3)&7] set seg [immediatef 1] set off [immediatef [sizeAd]] puts [format "l%s %s,%s" [lindex {es ds ss ?? fs gs} $type] [reg $reg [sizeAd]] $seg:$off] return 1 } proc lds {} { share return [les 1] } proc lock {} { share puts lock return 1 } proc lods {} { share puts "lods [reg 0 [sizeOp ($byte&1)]]" return 1 } proc loop {} { share set first $byte set rel [immediatef 0] if { $rel&0x80 } { incr rel 0xffffff00 } incr rel $pc puts [format "%s 0x%08x" [lindex {loopne loope loop} [expr $first&3]] $rel] lappend todos $rel return 1 } proc movs {} { share puts "movs[lindex {b w d} [sizeOp ($byte&1)]]" return 1 } proc mov {} { share if { ($byte&0xf8)==0xa0 } { set w [expr ($byte )&1] set d [expr ($byte>>1)&1] set off [immediatef [sizeAd]] set reg [reg 0 [sizeOp $w]] if { $d } { puts [format {mov %s,%s} $reg ($off)] } { puts [format {mov %s,%s} ($off) $reg] } return 1 } if { ($byte&0xf0)==0xb0 } { set w [expr ($byte>>3)&1] set reg [expr $byte &7] set size [sizeOp $w] set v [immediatef $size] puts [format {mov $%s,%s} $v [reg $reg $size]] return 1 } if { ($byte&0xfc)==0x8c } { set first $byte next set d [expr ($first>>1)&1] set mod [expr ($byte>>6)&3] set reg [expr ($byte>>3)&7] set rm [expr ($byte )&7] set reg [sreg3 $reg] set rm [modrm $mod $rm] if { $d } { puts [format {mov %s,%s} $rm $reg] } { puts [format {mov %s,%s} $reg $rm] } return 1 } if { ($byte&0xf8)==0x88 } { set first $byte next set w [expr ($first )&1] set d [expr ($first>>1)&1] set mod [expr ($byte>>6)&3] set reg [expr ($byte>>3)&7] set rm [expr ($byte )&7] set reg [reg $reg [sizeOp $w]] set rm [modrm $mod $rm $w] if { $d } { puts [format {mov %s,%s} $rm $reg] } { puts [format {mov %s,%s} $reg $rm] } return 1 } if { ($byte&0xfe)==0xc6 } { set first $byte next set w [expr ($first )&1] set mod [expr ($byte>>6)&3] set rm [expr ($byte )&7] set rm [modrm $mod $rm $w] set v [immediatef [sizeOp $w]] puts [format {mov $%s,%s} $v $rm] return 1 } error mov } proc nop {} { share puts nop return 1 } proc popf {} { share puts "pop[lindex {{} f {fd}} [sizeOp 1]]" return 1 } proc pop { {n ""}} { share if { $byte==0x07 } { puts "pop ds" return 1 } if { $byte==0x61 } { puts "popa" return 1 } if { $byte==0x17 } { puts "pop es" return 1 } if { $byte==0x1f } { puts "pop ds" return 1 } if { $byte==0x8f } { set next [next] set mod [expr ($next>>6)&3] set rm [expr $next &7] puts "pop [modrm $mod $rm]" return 1 } if { ($byte&0x58)==0x58 } { puts "pop [reg [expr $byte&7] [sizeOp]]" return 1 } puts "pop $n" return 1 } proc pushf {} { share puts "push[lindex {{} f {fd}} [sizeOp 1]]" return 1 } proc push { } { share if { ($byte&0xfd)==0x68 } { puts [format {push $%s} [immediatef [sizeOp [expr (~($byte>>1))&1]]]] return 1 } if { $byte==0x60 } { puts "pusha" return 1 } if { $byte==0x06 } { puts "push ds" return 1 } if { $byte==0x16 } { puts "push es" return 1 } if { $byte==0x1e } { puts "push ds" return 1 } if { $byte==0x0e } { puts "push cs" return 1 } if { $byte==0xff } { set next [next] set mod [expr ($next>>6)&3] set rm [expr $next &7] puts "push [modrm $mod $rm]" return 1 } if { ($byte&0x50)==0x50 } { puts "push [reg [expr $byte&7] [sizeOp]]" return 1 } error push } proc preLock {} { share set pre 1 set lock 1 puts lock return 1 } proc preSize { type } { share set pre 1 set swapSize$type 1 puts size$type return 1 } proc preSeg { type } { share set pre 1 puts "seg $type" return 1 } proc repe {} { share puts "repe" return 1 } proc rotation {} { share set first $byte next set w [expr $first&1] set type [expr ($byte>>3)&7] set mod [expr ($byte>>6)&3] set rm [expr ($byte )&7] set type [lindex { rol ror rcl rcr shl shr ? sar } $type] if { ($first&0xfe)==0xd0 } { set v "" } if { ($first&0xfe)==0xd2 } { set v ",%cl" } if { ($first&0xfe)==0xc0 } { set v ,$[immediatef 0] } puts [format {%s %s%s} $type [modrm $mod $rm $w] $v] return 1 } proc ret {} { share if { $byte == 0xc3 } { puts [format {ret}] return 1 } if { $byte == 0xc2 } { puts [format {ret %s} [immediatef 1]] return 1 } if { $byte == 0xca } { puts [format {ret far %s} [immediatef 1]] return 1 } if { $byte == 0xcb } { puts [format {ret}] return 1 } error ret return 0 } proc sahf {} { share puts sahf return 1 } proc scas {} { share set w [expr $byte&1] puts [format "scas,%s" [lindex {b w d} [sizeOp $w]]] return 1 } proc stc {} { share puts stc return 1 } proc std {} { share puts std return 1 } proc sti {} { share puts sti return 1 } proc stos {} { share puts "stos [reg 0 [sizeOp ($byte&1)]]" return 1 } proc test {} { share set w [expr $byte&1] if { ($byte&0xfe)==0xa8 } { set v [immediatef [sizeOp $w]] set reg [reg 0 [sizeOp $w]] puts [format {test $%s,%s,} $v $reg] } if { ($byte&0xfe)==0x84 } { next set mod [expr ($byte>>6)&3] set reg [expr ($byte>>3)&7] set rm [expr ($byte )&7] puts [format "test %s,%s" [reg 0 [sizeOp $w]] [modrm $mod $rm $w]] } return 1 } proc xchg {} { share if { ($byte&0xfe)==0x86 } { set w [expr ($byte )&1] next set mod [expr ($byte>>6)&3] set reg [expr ($byte>>3)&7] set rm [expr ($byte )&7] puts [format {xchg %s,%s} [reg 0 [sizeOp $w]] [modrm $mod $rm $w]] return 1 } if { ($byte&0xf8)==0x90 } { set reg [expr $byte&7] puts [format {xchg %s,%s} [reg 0 [sizeOp]] [reg $reg [sizeOp]]] return 1 } error xchg } proc xlat {} { share puts [format "xlat" ] return 1 } ###################################### proc lmerge { lname b e } { upvar $lname list set v [list] set p [list] #puts "--" #puts [format "0x%08x 0x%08x" $b $e] #puts "++" #foreach { bb ee } $list { # puts [format "0x%08x 0x%08x" $bb $ee] #} #puts "==" foreach { bb ee } $list { if { $ee<$b } { lappend v $bb $ee } if { $e<$bb } { lappend p $bb $ee } if { $bb<=$e && $e<=$ee } { set e $ee } if { $bb<=$b && $b<=$ee } { set b $bb } } set list [concat $v [list $b $e] $p] #foreach { bb ee } $list { # puts [format "0x%08x 0x%08x" $bb $ee] #} #puts "--" } proc lin { lname v } { upvar $lname list foreach { bb ee } $list { if { $bb<=$v && $v<$ee } { return 1 } } return 0 } proc diss { {dcnt 1} {file bios.reverse.S} {until 0} } { global reverse global win share set swapSizeAd 0 set swapSizeOp 0 set lock 0 set reverses [list] set havepc 0 while { $dcnt } { if { !$havepc } { while { !$havepc } { if { [llength $todos] } { set pc [lrange $todos 0 0] set todos [lrange $todos 1 end] } { break } if { ![lin dones $pc] } { set havepc 1 } } if { !$havepc } { break } { set reverse [list] lappend reverse {} lappend reverse [format " .org 0x%08lx" $pc] set seg(b) $pc } } incr dcnt -1 set address $pc set bytes [list] set pre 0 if { [catch { next set cmd $names($byte) set havepc [eval $cmd] } why] } { catch { next;next;next;next;next } puts [format "pb at 0x%08lx %s" $pc $why] #set seg(e) $pc #lmerge dones $seg(b) $seg(e) #lappend reverses $reverse #break set havepc 0 } if { !$pre } { set swapSizeAd 0 set swapSizeOp 0 set lock 0 } if { $havepc } { if { [lin dones $pc] } { set havepc 0 } } if { !$havepc } { set seg(e) $pc lmerge dones $seg(b) $seg(e) lappend reverses $reverse } if { $pc==$until } { break } } if { $havepc } { set seg(e) $pc lmerge dones $seg(b) $seg(e) lappend reverses $reverse } set f [open $file {WRONLY CREAT TRUNC}] fconfigure $f -buffersize [expr 1024*1024] #::puts $f [llength $reverses] foreach rs [lsort $reverses] { foreach r $rs { ::puts $f $r } } ::puts $f "" ::puts $f "dcnt : $dcnt" ::puts $f "havepc : $havepc" ::puts $f "" ::puts $f "dones :" set cumul 0 foreach { b e } $dones { ::puts $f [format "0x%08lx 0x%08lx" $b $e] incr cumul [expr $e-$b] } ::puts $f "$cumul" ::puts $f "" ::puts $f "todos :" foreach { td } $todos { ::puts $f [format "0x%08lx" $td] } close $f } } proc i386::load { file at } { share set model 16 set todos [list] set dones [list] set f [open $file {RDONLY}] fconfigure $f -translation binary set bin [read $f] close $f set bin_offset $at set bin_mask [string length $bin] incr bin_mask -1 } set i386::model 16 set i386::todos [list] set i386::dones [list] if 0 { lappend i386::todos 0xfffffff0 #bx lappend i386::todos 0x000f22c9 0x000f22d3 lappend i386::todos 0x000f2315 0x000f2325 0x000f2335 0x000f233f lappend i386::todos 0x000f24d3 0x000f24dc 0x000f24e4 0x000f24ed lappend i386::todos 0x000f2f71 #lappend i386::todos #di lappend i386::todos 0x000f22de 0x000f22e9 lappend i386::todos 0x000f234c 0x000f2354 0x000f235f 0x000f2368 0x000f2375 lappend i386::todos 0x000f2384 0x000f238d 0x000f2394 0x000f23a2 0x000f23a9 0x000f23b0 0x000f23bf 0x000f23ce lappend i386::todos 0x000f2e91 0x000f2e9c 0x000f2edb lappend i386::todos 0x000f2f0d 0x000f2f13 0x000f2f1e 0x000f2f24 0x000f2f44 0x000f2f8e 0x000f2f99 lappend i386::todos 0x000f72b7 0x000f72bd lappend i386::dones 0x000fa723 0x000fc000 lappend i386::dones 0x0007a723 0x0007c000 lappend i386::dones 0x0003b665 0x0003ffff i386::diss 32768 } if 0 { set f [open ../bios.bin {RDONLY}] fconfigure $f -translation binary set i386::bin_offset 0xf8000 set i386::bin [read $f] close $f puts stdout [string length $i386::bin] lappend i386::todos 0xfffffff0 i386::diss 32768 ../bios.bin.reverse.s } if 0 { set f [open ../tlabios/bios.bin {RDONLY}] fconfigure $f -translation binary set i386::bin_offset 0xfc000 set i386::bin [read $f] close $f string length $i386::bin lappend i386::todos 0xfffffff0 i386::diss 32768 ../tlabios/bios.bin.reverse.s } if 0 { set f [open ../bur.bin {RDONLY}] fconfigure $f -translation binary set i386::bin_offset 0x0700 set i386::bin [read $f] close $f string length $i386::bin lappend i386::todos 0x0700 i386::diss 32768 ../bur.bin.reverse.s } if 1 { set bytes { 0x8C 0xC8 0x8E 0xD8 0x8E 0xC0 0xFC 0xFA 0x8E 0xD0 0xBC 0xFE 0x7B 0xFB 0xBE 0xD4 0x7D 0xE8 0xEB 0x00 0x33 0xDB 0x8B 0xC3 0xA0 0x10 0x7C 0xF7 0x26 0x16 0x7C 0x8B 0x0E 0x0E 0x7C 0x03 0x0E 0x1C 0x7C 0x13 0x16 0x1E 0x7C 0x89 0x0E 0x03 0x7B 0x89 0x16 0x05 0x7B 0x03 0xC8 0x13 0xD3 0x89 0x0E 0x07 0x7B 0x89 0x16 0x09 0x7B 0x89 0x0E 0x0B 0x7B 0x89 0x16 0x0D 0x7B 0x52 0xB8 0x20 0x00 0xF7 0x26 0x11 0x7C 0x8B 0x36 0x0B 0x7C 0x03 0xC6 0x48 0xF7 0xF6 0x01 0x06 0x0B 0x7B 0x11 0x1E 0x0D 0x7B 0xA3 0x0F 0x7B 0x91 0x5A 0xBB 0x00 0x7E 0xE8 0xAE 0x00 0x73 0x03 0xE9 0x83 0x00 0xBE 0xEC 0x7D 0xFC 0x8B 0x0E 0x11 0x7C 0xBF 0x00 0x7E 0x51 0x56 0x57 0xB9 0x0B 0x00 0xF3 0xA6 0x5F 0x5E 0x59 0x74 0x0A 0x83 0xC7 0x20 0xE2 0xEE 0xBE 0xE9 0x7D 0xEB 0x64 0x8B 0x45 0x1C 0x8B 0x55 0x1E 0xF7 0x36 0x0B 0x7C 0xD1 0xE8 0xD1 0xE8 0x40 0xA3 0x11 0x7B 0xA1 0x0B 0x7C 0xD1 0xE8 0xD1 0xE8 0xA3 0x13 0x7B 0x8B 0x45 0x1A 0x48 0x48 0x33 0xC9 0x8A 0x0E 0x0D 0x7C 0xF7 0xE1 0x03 0x06 0x0B 0x7B 0x13 0x16 0x0D 0x7B 0xBB 0x00 0x08 0x8E 0xC3 0x33 0xDB 0xB1 0x04 0x50 0x52 0xE8 0x48 0x00 0x5A 0x58 0x72 0x1E 0xBE 0xF8 0x7D 0xE8 0x24 0x00 0xFF 0x0E 0x11 0x7B 0x74 0x0E 0x83 0xC0 0x04 0x83 0xD2 0x00 0x8C 0xC3 0x03 0x1E 0x13 0x7B 0xEB 0xD7 0xFF 0x2E 0x39 0x7D 0xBE 0xDE 0x7D 0xE8 0x06 0x00 0xEB 0xFE 0x00 0x00 0x00 0x08 0x53 0x50 0x80 0x3E 0xD3 0x7D 0x00 0x75 0x0E 0xAC 0x0A 0xC0 0x74 0x09 0xB4 0x0E 0xBB 0x07 0x00 0xCD 0x10 0xEB 0xF2 0x58 0x5B 0xC3 0xB5 0x02 0x57 0x88 0x0E 0x00 0x7B 0x8B 0xF0 0x8B 0xFA 0x89 0x1E 0x01 0x7B 0x8B 0xC6 0x8B 0xD7 0x8B 0x1E 0x18 0x7C 0xF7 0xF3 0x42 0x43 0x52 0x02 0xD1 0x3B 0xD3 0x5A 0x76 0x04 0xFE 0xC9 0xEB 0xF4 0x8B 0xDA 0x51 0x99 0xF7 0x36 0x1A 0x7C 0x86 0xE0 0xB1 0x06 0xD2 0xE0 0x91 0x0A 0xCB 0x8A 0xF2 0x58 0xB7 0x05 0x53 0x50 0x8B 0x1E 0x01 0x7B 0x8A 0x16 0xD2 0x7D 0x50 0xCD 0x13 0x58 0x32 0xE4 0x72 0x1F 0x59 0x5B 0x03 0xF0 0x83 0xD7 0x00 0x28 0x06 0x00 0x7B 0xF7 0x26 0x0B 0x7C 0x01 0x06 0x01 0x7B 0x8A 0x0E 0x00 0x7B 0x80 0xF9 0x00 0x77 0xA4 0xF8 0x5F 0xC3 0x33 0xC0 0xCD 0x13 0x58 0x5B 0xFE 0xCF 0x75 0xC5 0xF9 0xEB 0xF1 0x00 0x00 0x56 0x78 0x4C 0x64 0x20 0x31 0x2E 0x32 0x20 0x00 0x52 0x65 0x61 0x64 0x20 0x65 0x72 0x72 0x6F 0x72 0x00 0x4E 0x6F 0x20 0x42 0x4F 0x4F 0x54 0x52 0x4F 0x4D 0x20 0x53 0x59 0x53 0x00 0x2E 0x00 0x00 0x00 0x00 0xDF 0x55 0xAA } #http://www.xaff.org/GI/biosref.html #http://www.nondot.org/~sabre/os/articles/TheBootProcess/ set i386::bin_offset 0x7c00 set i386::bin [binary format a[expr 0x3e]c* "" $bytes ] binary scan $i386::bin H* hex lappend i386::todos 0x7c3e set i386::dones [list] set i386::bin_mask 0xffffffff i386::diss 512 vxboot.s } return set i386::model 16 set i386::todos [list] lappend i386::todos 0 set i386::dones [list] i386::diss 32768 return set win [messageWin rien] set f [open bios.bin {RDONLY}] fconfigure $f -translation binary set i386::bin_offset 0 set i386::bin [read $f] close $f string length $i386::bin set f [open bur.bin {RDONLY}] fconfigure $f -translation binary set i386::bin_offset 0xfd000 set i386::bin [read $f] close $f string length $i386::bin /* 0xffff2535 74 16 */ je 0xffff254d /* 0xffff2537 b8 1b 01 */ mov $0x011b,%ax /* 0xffff253a e7 24 */ out %ax,$0x24 /* 0xffff253c b8 10 02 */ mov $0x0210,%ax /* 0xffff253f e7 26 */ out %ax,$0x26 /* 0xffff2541 b8 1d 01 */ mov $0x011d,%ax /* 0xffff2544 e7 24 */ out %ax,$0x24 /* 0xffff2546 b8 d0 03 */ mov $0x03d0,%ax /* 0xffff2549 e7 26 */ out %ax,$0x26 /* 0xffff254b eb 14 */ jmp 0xffff2561 /* 0xffff254d b8 1b 01 */ mov $0x011b,%ax /* 0xffff2550 e7 24 */ out %ax,$0x24 /* 0xffff2552 b8 17 02 */ mov $0x0217,%ax /* 0xffff2555 e7 26 */ out %ax,$0x26 /* 0xffff2557 b8 1d 01 */ mov $0x011d,%ax /* 0xffff255a e7 24 */ out %ax,$0x24 /* 0xffff255c b8 d0 22 */ mov $0x22d0,%ax /* 0xffff255f e7 26 */ out %ax,$0x26 /* 0xffff2561 fc */ cld /* 0xffff2562 be 5f 24 */ mov $0x245f,%si /* 0xffff2565 ba 24 00 */ mov $0x0024,%dx /* 0xffff2568 b9 6c 00 */ mov $0x006c,%cx /* 0xffff256b d1 e9 */ shr %cx /* 0xffff256d 2e */ seg cs /* 0xffff256e 8b 04 */ mov (%si),%ax /* 0xffff2570 ef */ out %ax,%dx /* 0xffff2571 83 f2 02 */ xor $0x0002,%dx /* 0xffff2574 83 c6 02 */ add $0x0002,%si /* 0xffff2577 e2 f4 */ loop 0xffff256d /* 0xffff2579 e9 32 dc */ jmp 0xffff01ae expr 0x6c/2/2 at 0xffff245f 00000000 0110 0000 .... 00000004 0111 0000 .... 00000008 0112 0000 .... 0000000C 0113 0000 .... 00000010 0114 0000 .... 00000014 0115 0000 .... 00000018 0117 0000 .... 0000001C 0118 0000 .... 00000020 0119 006B ...k 00000024 011A 0220 ... 00000028 011E 0000 .... 0000002C 011F 0000 .... 00000030 0120 0000 . .. 00000034 0200 0000 .... 00000038 0201 0000 .... 0000003C 0202 0000 .... 00000040 0204 FFFF .... 00000044 0205 0000 .... 00000048 0207 FFFF .... 0000004C 0208 0000 .... 00000050 020A FFFF .... 00000054 020B 0000 .... 00000058 020D FFFF .... 0000005C 020E 0000 .... 00000060 020F 0000 .... 00000064 0213 0321 ...! 00000068 0214 0000 .... set i386::bin [binary format H* [join { 575051268A05E80B004726803D00E0F3 59585FC35250531EBB80006A001F80BF 850001752250BAFD03ECA82074F880BF 840000740ABAFE03EC24303C3075F958 BAF803EEE9AD0080BF8500020F85A400 8AD8BA1802EC50B07CEE42EC24FBEE4A B05EEE42EC24F1EEC0C302B908000653 9C6A0007BB80002681BFF10067F97420 1E515756B93B00BF6B020E1FBE2CF9F3 A426C605CB26C787F10067F95E5F591F 9D5B070E6867F96A00686B02CB4AB060 EE42ECA80275FB4AB05EEE42EC0C08EE 4AB060EE42ECA80274FB4AB05EEE42EC 5380E3020AC35BD0C324F7EE4AB060EE 42ECA80275FBE2CF4AB07CEE42EC0C04 EE4A58EE1F5B585AC35366561E526A00 1FBB800080BF85000175208B073B4702 74179CFA8B77028A40044681FE800075 0233F68977029DEB27EB2580BF850000 741E9C50BA1802EC50B080EEBA1A02ED F6C40174FA8AD8BA180258EE588AC39D 5A1F665E5BC31E536A001FBB8000FAC7 87EC000400FBE890FF750783BFEC0000 75F45B1FC3} ""]] string length $i386::bin set cc {C:/Tornado.2.0/host/x86-win32/i386-wrs-vxworks/bin/gcc} set ld {C:/Tornado.2.0/host/x86-win32/i386-wrs-vxworks/bin/ld} set objdump {C:/Tornado.2.0/host/x86-win32/bin/objdump386} exec gcc -c bios.reverse.S >bios.s proc diss { from len } { global objdump incr len $from exec $objdump \ --disassemble-all \ --target binary bios.bin \ --start-address=$from \ --stop-address=$len \ --architecture=i386 \ >>bios.reverse } return exec $objdump -i diss 0x3fff0 16 diss 0x32dd1 256