This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Ways to fill the stack


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]