为什么其他指针参数在程序集中消失了?指针、参数、消失了、程序

由网友(眉间上的悲痛)分享简介:C代码:void PtrArg1(int* a,int* b,int* c, int* d, int* e, int* f){return;}void PtrArg2(int* a,int* b,int* c, int* d, int* e, int* f, int* g, int* h){return;}使用...

C代码:

void PtrArg1(int* a,int* b,int* c, int* d, int* e, int* f)
{
    return;
}

void PtrArg2(int* a,int* b,int* c, int* d, int* e, int* f, int* g, int* h)
{
    return;
}

使用

编译
gcc -c -m64 -o basics basics.c -O0
分别用字符数组和字符指针作函数参数两种方法编程实现在字符串中删除与某字符相同的字符

正在运行

objdump -d basics -M intel -r

然后导致以下反汇编(英特尔语法):

000000000000000b <PtrArg1>:
   b:   f3 0f 1e fa             endbr64 
   f:   55                      push   rbp
  10:   48 89 e5                mov    rbp,rsp
  13:   48 89 7d f8             mov    QWORD PTR [rbp-0x8],rdi
  17:   48 89 75 f0             mov    QWORD PTR [rbp-0x10],rsi
  1b:   48 89 55 e8             mov    QWORD PTR [rbp-0x18],rdx
  1f:   48 89 4d e0             mov    QWORD PTR [rbp-0x20],rcx
  23:   4c 89 45 d8             mov    QWORD PTR [rbp-0x28],r8
  27:   4c 89 4d d0             mov    QWORD PTR [rbp-0x30],r9
  2b:   90                      nop
  2c:   5d                      pop    rbp
  2d:   c3                      ret    

000000000000002e <PtrArg2>:
  2e:   f3 0f 1e fa             endbr64 
  32:   55                      push   rbp
  33:   48 89 e5                mov    rbp,rsp
  36:   48 89 7d f8             mov    QWORD PTR [rbp-0x8],rdi
  3a:   48 89 75 f0             mov    QWORD PTR [rbp-0x10],rsi
  3e:   48 89 55 e8             mov    QWORD PTR [rbp-0x18],rdx
  42:   48 89 4d e0             mov    QWORD PTR [rbp-0x20],rcx
  46:   4c 89 45 d8             mov    QWORD PTR [rbp-0x28],r8
  4a:   4c 89 4d d0             mov    QWORD PTR [rbp-0x30],r9
  4e:   90                      nop
  4f:   5d                      pop    rbp
  50:   c3                      ret 
PtrArg1PtrArg2的参数数量不同,但两者的汇编指令是相同的。为什么?

推荐答案

这是由于调用约定(system V AMD64ABI,current version 1.0)。前六个参数在整数寄存器中传递,其他所有参数都被压入堆栈。

执行Until LocationPtrArg2+0x4e后,您会得到以下堆栈布局:

+----------+-----------------+
|  offset  |     content     |
+----------+-----------------+
| rbp-0x30 | f               |
| rbp-0x28 | e               |
| rbp-0x20 | d               |
| rbp-0x18 | c               |
| rbp-0x10 | b               |
| rbp-0x8  | a               |
| rbp+0x0  | saved rbp value |
| rbp+0x8  | return address  |
| rbp+0x10 | g               |
| rbp+0x18 | h               |
+----------+-----------------+

因为gh是由调用方推送的,所以两个函数得到相同的反汇编。对于呼叫者

void Caller()
{
    PtrArg2(1, 2, 3, 4, 5, 6, 7, 8);
}

(为清楚起见,我省略了必要的强制转换)我们将得到以下反汇编:

Caller():
    push    rbp
    mov     rbp, rsp
    push    8
    push    7
    mov     r9d, 6
    mov     r8d, 5
    mov     ecx, 4
    mov     edx, 3
    mov     esi, 2
    mov     edi, 1
    call    PtrArg2
    add     rsp, 16
    nop
    leave
    ret

(see compiler explorer)

参数h = 8g = 7在调用PtrArg2之前被推送到堆栈上。

阅读全文

相关推荐

最新文章