public function assemble() { #print 'jmp assemble'."\n"; $dst = $this->dst; $isStrDst = is_string($dst); if ($dst instanceof Instruction) { #\Doctrine\Common\Util\Debug::dump($dst, 1); #\Doctrine\Common\Util\Debug::dump($this, 1); #print "\t".'dst offset: '.$dst->getOffset()."\n"; #print "\t".'this offset: '.$this->getOffset()."\n"; $offset = $dst->getOffset() - $this->getOffset(); #print "\t".'diff: '.$offset."\n"; $orgOffset = $offset; $offset -= 2; if ($orgOffset < 0) { if ($offset < -0x80) { $offset -= 3; } #print "\t".'<- '.$offset."\n"; } $jmp = new Jmp($offset); $this->setOpcode($jmp->assemble()); $this->setLen($jmp->getLen()); } elseif (is_numeric($dst)) { #print "\t".'is numeric: '.$dst.' '.dechex($dst)."\n"; $base = 0; #$absDst = abs($dst); if ($dst >= -0x80 && $dst <= 0x7f) { $base = 0xeb00; $dst &= 0xff; $dst |= $base; #print "\t".'short label: '.dechex($dst)."\n"; } elseif ($dst >= -0x80000000 && $dst <= 0x7fffffff) { $base = 0xe900000000; $dst &= 0xffffffff; $dst = Num::be2le($dst, 4); $dst |= $base; #print "\t".'long label: '.dechex($dst)."\n"; } if ($base) { $opcode = dechex($dst); $opcodeLen = strlen($opcode); $this->setOpcode(pack('H*', $opcode)); $this->setLen($opcodeLen / 2); } } elseif ($isStrDst) { $strLenDst = strlen($dst); if ($strLenDst == 2) { $jmp = new X86Jmp($dst); $this->setOpcode(pack('H*', '66') . $jmp->assemble()); $this->setLen($jmp->getLen() + 1); } elseif ($strLenDst == 3) { $base = 0xffe0; switch ($dst[1]) { /*case 'a': $base += 0; break;*/ case 'c': $base++; break; case 'd': $base += 2; break; case 'b': $base += 3; break; } $opcode = dechex($base); $opcodeLen = strlen($opcode); $this->setOpcode(pack('H*', $opcode)); $this->setLen($opcodeLen / 2); } } return $this->getOpcode(); }
public function testI386Self() { $jmp1 = new I386Jmp(0); $jmp1->dst = $jmp1; $jmp1->setOffset(10); $opcode = unpack('H*', $jmp1->assemble()); $opcode = $opcode[1]; $this->assertEquals('ebfe', $opcode); }