Ways to fill the stack
sztfg@yandex.ru
sztfg@yandex.ru
Mon Feb 11 10:02:00 GMT 2013
10.02.2013, 21:44, "Ian Lance Taylor" <iant@google.com>:
> On Sat, Feb 9, 2013 at 10:42 PM, б <sztfg@yandex.ru> wrote:
>
>> б 10.02.2013, 10:13, "Ian Lance Taylor" <iant@google.com>:
>>> б б I don't see why this would ever use a push instruction. б Arguments are
>>> б б passed in registers on x86_64. б For each call the local array is built
>>> б б on the stack, then the address of the array is passed in a register.
>> б Local array can be build on the stack, using push instruction.
>
> Sure, but why would that be a good idea?
>
> In any case GCC does not generally use push instructions for local
> variables. б Instead GCC allocates a frame on the stack, and fills in
> values as needed. б GCC does in some cases use push instructions to
> push arguments to functions. б Is there any reason that GCC should use
> push instructions for local variables?
>
> Ian
For this case:
#define setarr(a) [sizeof(a)-1] = (a) // remove NULL from end of string
void foo(void)
{
const char a2 setarr(
"0000""0000"
"0001""0001"
"0002""0002"
"0003""0003"
"0004""0004"
"0005""0005");
bar(a2);
return;
}
with gcc -c -march=native -O2 sample.c -o sample.o
I got this:
Disassembly of section .text:
0000000000000000 <foo>:
0: 48 83 ec 38 sub $0x38,%rsp
4: 49 b8 30 30 30 30 30 movabs $0x3030303030303030,%r8
b: 30 30 30
e: 48 bf 30 30 30 31 30 movabs $0x3130303031303030,%rdi
15: 30 30 31
18: 4c 89 04 24 mov %r8,(%rsp)
1c: 48 89 7c 24 08 mov %rdi,0x8(%rsp)
21: 48 be 30 30 30 32 30 movabs $0x3230303032303030,%rsi
28: 30 30 32
2b: 48 b9 30 30 30 33 30 movabs $0x3330303033303030,%rcx
32: 30 30 33
35: 48 89 74 24 10 mov %rsi,0x10(%rsp)
3a: 48 89 4c 24 18 mov %rcx,0x18(%rsp)
3f: 48 ba 30 30 30 34 30 movabs $0x3430303034303030,%rdx
46: 30 30 34
49: 48 b8 30 30 30 35 30 movabs $0x3530303035303030,%rax
50: 30 30 35
53: 48 89 54 24 20 mov %rdx,0x20(%rsp)
58: 48 89 44 24 28 mov %rax,0x28(%rsp)
5d: 48 89 e7 mov %rsp,%rdi
60: 31 c0 xor %eax,%eax
62: e8 00 00 00 00 callq 67 <foo+0x67>
67: 48 83 c4 38 add $0x38,%rsp
6b: c3 retq
As you can see, mov %r8,(%rsp) produse 4 bytes: 4c 89 04 24 and mov %rdi,0x8(%rsp) produces 5 bytes: 48 89 7c 24 08
push %r8 produces only 2 byte 41 50 and push %rax (or %rcx %rdx ...) produces one byte
You can check other instruction length, for example movq %rax, (%rsp) etc.
If we need to load bigger chunk to the stack:
#define setarr(a) [sizeof(a)-1] = (a) // remove NULL from end of string
void foo(void)
{
const char a2 setarr(
"0000""0000"
"0001""0001"
"0002""0002"
...
"0017""0017"
"0018""0018"
"0019""0019");
bar(a2);
return;
}
it produce this:
...
.LC0:
.string "0000000000010001000200...
...
movl $.LC0, %esi
movq %rsp, %rdi
movl $20, %ecx
xorl %eax, %eax
rep movsq
movq %rsp, %rdi
call bar
...
This can be replaced (for very large data) to something like http://build.shr-project.org/sources/svn/www.eglibc.org/svn/branches/eglibc-2_14/libc/sysdeps/x86_64/multiarch/memcpy-ssse3.S
Unfortunately, x86-64 can't push xmm
More information about the Gcc-help
mailing list