2010-11-22 9 views
3

私はアセンブラを学んでいて、次のような驚くべきものがいくつか見つかりました。私は基本的に私はNASM -fエルフ-g hellow.asm、LD hellow.o -o hellowでこれをコンパイルしてリンクするNASM&GDB:最初の命令を失う

section .text 
    global _start 

_start: 
    mov edx,len 
    mov ecx,msg 
    mov ebx,1 
    mov eax,4 
    int 0x80  ; interrupt for calling kernel 

    mov eax,1 
    int 0x80 

section .data 

msg db 'Hello, world!',0xa 
len equ $ - msg 

インターネット上のどこかからいくつかのhello世界のコードをコピーしました。今私はgdbにロードする場合、私はコードを一覧表示し、それを実行するだけで良い。最初のmov命令にブレークポイントを置くと、プログラムはそこで停止しません。私が得る結果のファイルにndisasm(ndisasm -b32 hellow)(と思う部分が関連している)の実行:

0000007D 0000    add [eax],al 
0000007F 00BA0E000000  add [edx+0xe],bh 
00000085 B9A0900408  mov ecx,0x80490a0 
0000008A BB01000000  mov ebx,0x1 
0000008F B804000000  mov eax,0x4 
00000094 CD80    int 0x80 
00000096 B801000000  mov eax,0x1 
0000009B CD80    int 0x80 

をので、指示が表示されません。

何が起こっているのか、何が起きているのかを知ることができます。

答えて

1

逆アセンブルで命令が正しく表示されない理由は、ディスアセンブルを開始した場所と命令がどのように落ちるかの問題です。 x86には可変長命令があるため、逆アセンブラはエントリポイントを知る必要があります。正しいリストはもっと似ている:

00000080 BA0E000000  mov edx,0xe ; I think 
00000085 B9A0900408  mov ecx,0x80490a0 
... 

本当の問題は、おそらくあなたはGDBが最初の命令の前に破壊にチョーク場合、私は思い出すことができない、ブレークポイントを設定する(プラスしているどのようにして、それが思わgdbであります、私はチェックしなければならないだろう)。

+0

実際、ndisasm:ndisasm -b32 -s0X80 hellowに「同期点」を追加することで、これらの命令が見つかりました。その後、指示どおりにデコードされます。私は私のバイナリ形式には開始点が80であるという情報が含まれていると仮定していますが、readelfは_startが08048080であることを示唆しています。 – kasterma

+0

@kasterma IIRC実行ファイルの先頭は実際にはlinux/386のメモリアドレス0x08048000です。 – cthom06

+1

gccをリンクに使用すると、はるかに大きな実行可能ファイルが得られますが、最初の命令に機能停止ブレークポイントを置くことができます。 – kasterma