0

引数を出力するためのACプログラムを作成しました

#include<stdio.h>
void main( int argc, char *argv[])
{
int i=0;
for(i=0;i<argc;i++)
printf("argument %d=%s\n",i,argv[i]);
}

私が得たgdbを使用した上記のプログラムのアセンブリダンプは.

Dump of assembler code for function main:
0x00000000004004f4 <+0>:    push   %rbp
0x00000000004004f5 <+1>:    mov    %rsp,%rbp
0x00000000004004f8 <+4>:    sub    $0x20,%rsp
0x00000000004004fc <+8>:    mov    %edi,-0x14(%rbp)
0x00000000004004ff <+11>:   mov    %rsi,-0x20(%rbp)
0x0000000000400503 <+15>:   movl   $0x0,-0x4(%rbp)
0x000000000040050a <+22>:   movl   $0x0,-0x4(%rbp)
0x0000000000400511 <+29>:   jmp    0x40053e <main+74>
0x0000000000400513 <+31>:   mov    -0x4(%rbp),%eax
0x0000000000400516 <+34>:   cltq   
0x0000000000400518 <+36>:   shl    $0x3,%rax
0x000000000040051c <+40>:   add    -0x20(%rbp),%rax
0x0000000000400520 <+44>:   mov    (%rax),%rdx
0x0000000000400523 <+47>:   mov    $0x40063c,%eax
0x0000000000400528 <+52>:   mov    -0x4(%rbp),%ecx
0x000000000040052b <+55>:   mov    %ecx,%esi
0x000000000040052d <+57>:   mov    %rax,%rdi
0x0000000000400530 <+60>:   mov    $0x0,%eax
0x0000000000400535 <+65>:   callq  0x4003f0 <printf@plt>
0x000000000040053a <+70>:   addl   $0x1,-0x4(%rbp)
0x000000000040053e <+74>:   mov    -0x4(%rbp),%eax
0x0000000000400541 <+77>:   cmp    -0x14(%rbp),%eax
0x0000000000400544 <+80>:   jl     0x400513 <main+31>
0x0000000000400546 <+82>:   leaveq 
0x0000000000400547 <+83>:   retq   
End of assembler dump.

今私が欲しいのは、「引数が渡されるメモリ位置(アドレス)です。たとえば、プログラムを「arg 1」として実行すると、引数が出力されます。この引数を抽出している命令を知りたいです。または、どのレジスタが引数を保持しますか(複数の引数を渡す場合も同様です..(これは、それが存在するメモリアドレスを教えてくれますか?)

4

2 に答える 2

2

この引数を抽出している命令、または引数を保持しているレジスタを知りたい

この種の質問には、ターゲット マシンのアセンブリ言語のリファレンス マニュアルを入手し、それを調べることによって最もよく答えられます。ただし、特定の質問は、アセンブリ言語の詳細に精通していなくても、調べれば簡単に答えられます。

0x0000000000400503 <+15>:   movl   $0x0,-0x4(%rbp)
0x000000000040050a <+22>:   movl   $0x0,-0x4(%rbp)

これは、冗長i = 0ステートメント用に生成されたコードです。

0x0000000000400513 <+31>:   mov    -0x4(%rbp),%eax

の値iは現在 %eax レジスタにあります。

0x0000000000400518 <+36>:   shl    $0x3,%rax
0x000000000040051c <+40>:   add    -0x20(%rbp),%rax

これにより、アドレスが計算さargv[i]れ、%rax レジスタに格納されます。

0x0000000000400520 <+44>:   mov    (%rax),%rdx

これにより、 の値がargv[i]%rdx レジスタにロードされます。引数としておよびを使用した呼び出しに続くコードprintfiargv[i]

今私が欲しいのは「引数が渡されるメモリの場所(アドレス)です。

asm を見て argc の値を判断できるのと同じように、asm を見てそれを判断することはできません。これらはさまざまな値であり、実際にプログラムを実行したときにのみ決定されます。実行時にアドレスを決定したい場合は、次を使用できます

printf("address of argv = %p\n", (void*)argv);

それが必要な場合は、asm をダンプしてその意味を学習する必要はなく、目的には関係ありません。

于 2012-10-01T19:52:16.403 に答える
1

デバッグに使用gdbしているので、Linuxを使用していると思います。次に、gcc -S -Wall -fverbose-asm foo.c(おそらくのような最適化フラグを使用して)を使用して、ファイルが(に置き換えられている場合)であると仮定して-O2、より理解しやすいfoo.sアセンブリファイルを取得します。次に、エディター(またはなど)で内部を確認します。foo.chello.cfoohellofoo.sgeditemacs

そして、それmainはほとんど普通の関数であり(その署名は標準で許可されているものでなければならないことを除いて、例えばint main(int argc, char**argv)....)、それはによって呼び出されcrt0.oます(コンパイルしgcc -vてどれを学ぶか)。

Linux Assembly Howto、たとえばx86-64ABIx86呼び出し規約のwikiページを読むことをお勧めします。

最適化フラグ(-O1または-O2)がない場合、gccコンパイラーは非常に単純なコードを生成することに注意してください。

于 2012-10-01T19:00:05.883 に答える