LINUX.ORG.RU

[x86_64/asm/c] использование параметров в C-функции


0

1

Согласно x86_64 ABI (http://www.x86-64.org/documentation/abi.pdf) параметры в C-функцию передаются через регистры... Отлично! Однако, допустим, есть следующий стартап код (test.s):

.text
.globl _start
_start:

xorq %rbp, %rbp		# set frame pointer to zerro, as per abi

popq	%rdi				# %rdi = argc
movq	%rsp, %rsi		# %rsi = argv

movq	%rdi, %rax
incq	%rax
shlq	$3, %rax
movq	%rsp, %rdx
addq	%rax, %rdx		# %rdx = arge

andq	$-16, %rsp		# align stack pointer to 16 bytes
pushq	%rax				# garbage (8 bytes)
pushq	%rsp				# stack pointer (8 bytes)

call main

movq %rax, %rdi		# %rax - retvalue
movq $60, %rax			# 60 - exit syscall number
syscall

Также есть функция main (test.c):

int main( int argc, char** argv, char** arge ) {
	int i;
	for( i=0; arge[i]; ++i );
	return i;
}

Далее компилируем, убираем лишнее и дизассемблируем:

$ gcc -nostdinc -nostdlib -fno-builtin -o test test.s test.c
$ strip ./test
$ objdump -d ./test

Получаем следующий дамп:

./test:     file format elf64-x86-64

Disassembly of section .text:

00000000004000b0 <.text>:

# _start:
  4000b0:       48 31 ed                xor    %rbp,%rbp
  4000b3:       5f                      pop    %rdi
  4000b4:       48 89 e6                mov    %rsp,%rsi
  4000b7:       48 89 f8                mov    %rdi,%rax
  4000ba:       48 ff c0                inc    %rax
  4000bd:       48 c1 e0 03             shl    $0x3,%rax
  4000c1:       48 89 e2                mov    %rsp,%rdx
  4000c4:       48 01 c2                add    %rax,%rdx
  4000c7:       48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
  4000cb:       50                      push   %rax
  4000cc:       54                      push   %rsp

# call main
  4000cd:       e8 0e 00 00 00          callq  0x4000e0
  4000d2:       48 89 c7                mov    %rax,%rdi
  4000d5:       48 c7 c0 3c 00 00 00    mov    $0x3c,%rax
  4000dc:       0f 05                   syscall
  4000de:       90                      nop
  4000df:       90                      nop

# main
  4000e0:       55                      push   %rbp
  4000e1:       48 89 e5                mov    %rsp,%rbp

# !!! move parameters back to memory
  4000e4:       89 7d ec                mov    %edi,0xffffffffffffffec(%rbp)
  4000e7:       48 89 75 e0             mov    %rsi,0xffffffffffffffe0(%rbp)
  4000eb:       48 89 55 d8             mov    %rdx,0xffffffffffffffd8(%rbp)
  4000ef:       c7 45 fc 00 00 00 00    movl   $0x0,0xfffffffffffffffc(%rbp)
  4000f6:       eb 04                   jmp    0x4000fc
  4000f8:       83 45 fc 01             addl   $0x1,0xfffffffffffffffc(%rbp)
  4000fc:       8b 45 fc                mov    0xfffffffffffffffc(%rbp),%eax
  4000ff:       48 98                   cltq
  400101:       48 c1 e0 03             shl    $0x3,%rax
  400105:       48 03 45 d8             add    0xffffffffffffffd8(%rbp),%rax
  400109:       48 8b 00                mov    (%rax),%rax
  40010c:       48 85 c0                test   %rax,%rax
  40010f:       75 e7                   jne    0x4000f8
  400111:       8b 45 fc                mov    0xfffffffffffffffc(%rbp),%eax
  400114:       c9                      leaveq
  400115:       c3                      retq

Из которого видно, что параметры, переданные в функцию main, перекладываются из регистров в память, и потом уже используются...

Это - что, шутка такая? (:

Почему не юзаются непосредственно регистры?


Ответ на: комментарий от anonymous

точно. после трех «no» об O3 совсем забыл)

так выглядит уже куда достойнее:

./test:     file format elf64-x86-64

Disassembly of section .text:

00000000004000b0 <.text>:
  4000b0:       48 31 ed                xor    %rbp,%rbp
  4000b3:       5f                      pop    %rdi
  4000b4:       48 89 e6                mov    %rsp,%rsi
  4000b7:       48 89 fa                mov    %rdi,%rdx
  4000ba:       48 ff c2                inc    %rdx
  4000bd:       48 c1 e2 03             shl    $0x3,%rdx
  4000c1:       48 01 e2                add    %rsp,%rdx
  4000c4:       57                      push   %rdi
  4000c5:       e8 16 00 00 00          callq  0x4000e0
  4000ca:       48 89 c7                mov    %rax,%rdi
  4000cd:       48 c7 c0 3c 00 00 00    mov    $0x3c,%rax
  4000d4:       0f 05                   syscall
  4000d6:       90                      nop
  4000d7:       90                      nop
  4000d8:       90                      nop
  4000d9:       90                      nop
  4000da:       90                      nop
  4000db:       90                      nop
  4000dc:       90                      nop
  4000dd:       90                      nop
  4000de:       90                      nop
  4000df:       90                      nop
  4000e0:       31 c9                   xor    %ecx,%ecx
  4000e2:       48 83 3a 00             cmpq   $0x0,(%rdx)
  4000e6:       74 10                   je     0x4000f8
  4000e8:       48 8b 42 08             mov    0x8(%rdx),%rax
  4000ec:       83 c1 01                add    $0x1,%ecx
  4000ef:       48 83 c2 08             add    $0x8,%rdx
  4000f3:       48 85 c0                test   %rax,%rax
  4000f6:       75 f0                   jne    0x4000e8
  4000f8:       89 c8                   mov    %ecx,%eax
  4000fa:       c3                      retq

mrs ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.