7

JMPx86プラットフォーム用のアセンブラを構築しているときに、命令のエンコードでいくつかの問題が発生しました。

OPCODE   INSTRUCTION   SIZE
 EB cb     JMP rel8     2
 E9 cw     JMP rel16    4 (because of 0x66 16-bit prefix)
 E9 cd     JMP rel32    5
 ...

私のお気に入りのx86命令Webサイト、http://siyobik.info/index.php?module = x86&id = 147から)

すべて相対ジャンプであり、各エンコーディング(演算+オペランド)のサイズは3番目の列にあります。

現在、私の元の(したがってこのために障害がある)設計では、各命令に最大(5バイト)のスペースが予約されています。オペランドはまだ不明な場所へのジャンプであるため、まだ不明です。NOPそこで、ジャンプの場所がわかっている場合は、メモリ内の正しい場所にオペランドを再書き込みし、残りをsで埋める、「再書き込み」メカニズムを実装しました。これは、タイトループではやや深刻な問題です。

今私の問題は次の状況にあります:

b: XXX
c: JMP a
e: XXX
   ...
   XXX
d: JMP b
a: XXX      (where XXX is any instruction, depending
             on the to-be assembled program)

JMP問題は、命令 に対して可能な限り最小のエンコーディングが必要なことです(そしてNOP塗りつぶしは必要ありません)。

のオペランド間のc相対距離を計算する前に、の命令のサイズを知る必要があります。同じことがatにも当てはまります。との間の相対距離を計算する前に、のサイズを知る必要があります。abdJMPcdea

既存のアセンブラはこの問題をどのように解決しますか、またはこれをどのように行いますか?

これは私が問題を解決すると考えていることです:

最初に、とそのターゲットの間のオペコードへのすべての命令をエンコードします。JMPこの領域に可変サイズのオペコードが含まれている場合は、最大サイズを使用します(例5JMP。次に、JMP可能な限り最小のエンコードサイズ(3、4、または5)を選択して、ターゲットを基準にしてエンコードし、距離を計算します。可変サイズのオペコードがエンコードされている場合は、前にすべての絶対オペランドを変更し、このエンコードされた命令をスキップするすべての相対命令を変更します。オペランドが変更されると、可能な限り最小のサイズを選択するように再エンコードされます。可変サイズのオペコードは(最大サイズを使用するため)縮小する可能性があるため、このメソッドは確実に終了します。

おそらくこれは過剰に設計されたソリューションなのだろうか、それが私がこの質問をする理由です。

4

2 に答える 2

3

jmp最初のパスでは、すべてのジャンプ命令に悲観的なバイトカウントを使用して、どのコードを使用するかを非常によく近似します。

2番目のパスでは、選択した悲観的なオペコードをジャンプに入力できます。その後、1バイトまたは2バイト少ないジャンプを使用するように書き換えることができるジャンプはごくわずかで、元々8/16ビットまたは16/32バイトのジャンプしきい値に非常に近いものだけでした。候補はすべて数バイトのジャンプであるため、クリティカルループの状況になる可能性は低く、2パスソリューションに比べてパスが増えるとほとんどまたはまったくメリットがないことがわかります。

于 2010-05-11T21:40:53.943 に答える
1

これが私が使用した1つのアプローチで、非効率に見えるかもしれませんが、ほとんどの実際のコード(擬似コード)には当てはまらないことがわかります。

IP := 0;
do
{
  done = true;
  while (IP < length)
  {
    if Instr[IP] is jump
      if backwards
      { Target known
          Encode short/long as needed }
      else
      {  Target unknown
          if (!marked as needing long encoding) // see below
            Encode short
          Record location for fixup }
    IP++;
  }
  foreach Fixup do
    if Jump > short
      Mark Jump location as requiring long encoding
      PC := FixupLocation; // restart at instruction that needs size change
      done = false; 
      break; // out of foreach fixup
    else
      encode jump
} while (!done);
于 2010-05-11T22:21:32.033 に答える