スタックの内容は、次のものに大きく依存します。
- CPU
- コンパイラ
- 呼び出し規則 (つまり、パラメーターがレジスターおよびスタックでどのように渡されるか)
- コンパイラによって実行されるコードの最適化
これは、次を使用して x86 mingw で小さなプログラムをコンパイルすることで得られるものですgcc stk.c -S -o stk.s
。
.file "stk.c"
.def ___main; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC0:
.ascii "SomeString\0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
LFB6:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
call ___main
movl $LC0, 28(%esp)
movl 12(%ebp), %eax
addl $4, %eax
movl (%eax), %eax
movl %eax, (%esp)
call _printf
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE6:
.def _printf; .scl 2; .type 32; .endef
そして、これは私が を使用して得たものですgcc stk.c -S -O2 -o stk.s
。つまり、最適化が有効になっています。
.file "stk.c"
.def ___main; .scl 2; .type 32; .endef
.section .text.startup,"x"
.p2align 2,,3
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
LFB7:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $16, %esp
call ___main
movl 12(%ebp), %eax
movl 4(%eax), %eax
movl %eax, (%esp)
call _printf
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE7:
.def _printf; .scl 2; .type 32; .endef
ご覧のとおり、後者の場合、スタックに "SomeString" へのポインターはありません。実際、この文字列はコンパイルされたコードには存在しません。
この単純なコードでは、スタックに保存されるレジスタはありません。これは、 への呼び出し全体で保持する必要があるレジスタに割り当てられた変数がないためprintf()
です。
したがって、ここでスタック上に得られるのは、文字列ポインタ (オプション)、スタック アラインメントによる未使用スペース ( andl $-16, %esp
+スタックをアラインsubl $32, %esp
してローカル変数にスペースを割り当てる、ここではなし)、printf()
のパラメータ、の戻りアドレスだけです。からprintf()
に戻るmain()
。
前者の場合、"SomeString" へのポインターとprintf()
のパラメーター ( の値argv[1]
) は互いにかなり離れています。
movl $LC0, 28(%esp) ; address of "SomeString" is at esp+28
movl 12(%ebp), %eax
addl $4, %eax
movl (%eax), %eax
movl %eax, (%esp) ; address of a copy of argv[1] is at esp
call _printf
2 つのアドレスをスタックに次々に格納するには、それが必要な場合は、コード、コンパイル/最適化オプションを操作するか、別のコンパイラを使用する必要があります。
または、それに到達するargv[1]
ようなフォーマット文字列を指定することもできます。printf()
たとえば、フォーマット文字列にいくつかの偽のパラメーターを含めることができます。
たとえば、このコードを を使用してコンパイルしgcc stk.c -o stk.exe
、 として実行するとstk.exe %u%u%u%u%u%u%s
、次の出力が得られます。
4200532268676042006264200532880015253SomeString
これはすべてかなりハックであり、正しく機能させるのは簡単ではありません。