0

ランダムに生成されたアセンブリを読み、適切な入力を入力して、explode_bomb 関数を呼び出さずに最後に到達する必要があります。問題は、真っ向から矛盾しているように見える 2 つの行があり、ランダム生成のために割り当てが実際には不可能ではないか心配です。

完全なコードは次のとおりです。

 08048d1b <phase_2>:
 8048d1b:       55                      push   %ebp
 8048d1c:       89 e5                   mov    %esp,%ebp
 8048d1e:       56                      push   %esi
 8048d1f:       53                      push   %ebx
 8048d20:       83 ec 30                sub    $0x30,%esp
 8048d23:       8d 45 e0                lea    0xffffffe0(%ebp),%eax
 8048d26:       89 44 24 04             mov    %eax,0x4(%esp)
 8048d2a:       8b 45 08                mov    0x8(%ebp),%eax
 8048d2d:       89 04 24                mov    %eax,(%esp)
 8048d30:       e8 42 04 00 00          call   8049177 <read_six_numbers>
 8048d35:       83 7d e0 00             cmpl   $0x0,0xffffffe0(%ebp)
 8048d39:       79 05                   jns    8048d40 <phase_2+0x25>
 8048d3b:       e8 f5 03 00 00          call   8049135 <explode_bomb>
 8048d40:       bb 01 00 00 00          mov    $0x1,%ebx
 8048d45:       8d 75 e0                lea    0xffffffe0(%ebp),%esi
 8048d48:       89 d8                   mov    %ebx,%eax
 8048d4a:       03 44 9e fc             add    0xfffffffc(%esi,%ebx,4),%eax
 8048d4e:       39 04 9e                cmp    %eax,(%esi,%ebx,4)
 8048d51:       74 05                   je     8048d58 <phase_2+0x3d>
 8048d53:       e8 dd 03 00 00          call   8049135 <explode_bomb>
 8048d58:       83 c3 01                add    $0x1,%ebx
 8048d5b:       83 fb 06                cmp    $0x6,%ebx
 8048d5e:       75 e8                   jne    8048d48 <phase_2+0x2d>
 8048d60:       83 c4 30                add    $0x30,%esp
 8048d63:       5b                      pop    %ebx
 8048d64:       5e                      pop    %esi
 8048d65:       5d                      pop    %ebp
 8048d66:       c3                      ret  

問題の行は 8048d4a と 8048d4e です。これは 2 の補数であるため、最初の数字は -4 で、2 番目の数字は最初の入力 (これは 2 番目と 3 番目に変わることさえありますか?) であり、3 番目はループの繰り返しになります。 4番目と同様に。

これらの値を直接の順序で比較するということは、基本的に、数値をそれ自体と比較していることを意味します - 4 ですね。どうすればそのテストに合格できるでしょうか?

ご協力いただきありがとうございます。

4

2 に答える 2

3

私のAT&T構文は最高ではありませんが、それはやっているようです:

ADD EAX,[ESI + EBX * 4 - 4]
CMP EAX,[ESI + EBX * 4]

別名、前のカウンターといくつかのカウンターの合計を現在のエントリと比較します。具体的には、これを参照してください。

Example:
Intel Syntax
instr   foo,segreg:[base+index*scale+disp]
mov     eax,[ebx+20h]
add     eax,[ebx+ecx*2h
lea     eax,[ebx+ecx]
sub     eax,[ebx+ecx*4h-20h]
AT&T Syntax
instr   %segreg:disp(base,index,scale),foo
movl    0x20(%ebx),%eax
addl    (%ebx,%ecx,0x2),%eax
leal    (%ebx,%ecx),%eax
subl    -0x20(%ebx,%ecx,0x4),%eax

このようにする理由については、レジスタのスピルを回避するための最適化、または配列インデックスをデクリメントしてからインクリメントするという代替手段のようです。

于 2012-11-04T15:17:51.790 に答える
0
mov    $0x1,%ebx                        ; i = 1
lea    0xffffffe0(%ebp),%esi            ; ESI = address of array of 6 numbers
mov    %ebx,%eax                        
add    0xfffffffc(%esi,%ebx,4),%eax     ; add to element
cmp    %eax,(%esi,%ebx,4)

add    0xfffffffc(%esi,%ebx,4),%eax

上記の命令は、配列の要素にアクセスしています。これはx86 ではSIBアドレッシングと呼ばれ、Scale、Index、Base に対応します。オフセット コンポーネントもあります。配列は、ベース レジスタ (EBXここでは) とオフセット (ここでは -4) によって決定されるアドレスに基づいています。要素番号は Index レジスタ (ESIここ) にあります。各要素のサイズは Scale (ここでは 4) によって決まります。

lea    0xffffffe0(%ebp),%esi            ; ESI = address of array of 6 numbers

さらに上を見ると、配列のアドレスがどのように に移動されているかがわかります%ESI。配列は、フレーム ポインターの 32 バイト下にあるローカル変数です (フレーム ポインターを使用する場合、配列を含むローカル変数は、フレーム ポインターからのオフセットとしてアドレス指定されます)。

add    0xfffffffc(%esi,%ebx,4),%eax

したがって、この命令は、実際の配列の 4 バイト前から始まる「仮想」配列にアクセスします。これは、ループ インデックスが 1 から始まるためですが、アクセスされる要素は 0 であるため、「仮想配列」を使用するとすべてが適切に機能します。

mov    $0x1,%ebx                        ; i = 1
lea    0xffffffe0(%ebp),%esi            ; ESI = address of array of 6 numbers
mov    %ebx,%eax                        
add    0xfffffffc(%esi,%ebx,4),%eax     ; add to element i-1
cmp    %eax,(%esi,%ebx,4)               ; compare against element i
于 2012-11-04T15:29:18.717 に答える