Assembly Arm程序集-使用4个以上参数调用函数

Assembly Arm程序集-使用4个以上参数调用函数,assembly,stack,arm,disassembly,Assembly,Stack,Arm,Disassembly,我知道在程序集中调用函数时,r0包含第一个参数,而r3是第四个参数。我知道当它超过4时,会使用堆栈指针,但具体细节我不太确定。r0-r3是否仍保留前四个,而其余的则保留在堆栈上?我正在看下面的程序集,试图理解调用mach_msg(一个有七个参数的函数)的过程。在输入此代码时,r0和r1包含两个参数 var_38 = -0x38 var_34 = -0x34 var_30 = -0x30 var_2C = -0x2C var_

我知道在程序集中调用函数时,r0包含第一个参数,而r3是第四个参数。我知道当它超过4时,会使用堆栈指针,但具体细节我不太确定。r0-r3是否仍保留前四个,而其余的则保留在堆栈上?我正在看下面的程序集,试图理解调用mach_msg(一个有七个参数的函数)的过程。在输入此代码时,r0和r1包含两个参数

var_38          = -0x38
var_34          = -0x34
var_30          = -0x30
var_2C          = -0x2C
var_24          = -0x24
var_20          = -0x20
var_18          = -0x18
var_14          = -0x14
var_10          = -0x10
var_C           = -0xC
00001220
00001220                 PUSH            {R7,LR}
00001222                 MOV             R7, SP
00001224                 SUB             SP, SP, #0x30
00001226                 MOV             R2, (_NDR_record_ptr - 0x1232) ; _NDR_record_ptr
0000122E                 ADD             R2, PC ; _NDR_record_ptr
00001230                 LDR             R2, [R2] ; _NDR_record
00001232                 LDR             R3, [R2]
00001234                 LDR             R2, [R2,#4]
00001236                 STR             R2, [SP,#0x38+var_10]
00001238                 MOVS            R2, #0x24 ; '$'
0000123A                 STR             R3, [SP,#0x38+var_14]
0000123C                 MOVS            R3, #0
0000123E                 STRB.W          R1, [SP,#0x38+var_C]
00001242                 MOVS            R1, #0x13
00001244                 STR             R1, [SP,#0x38+var_2C]
00001246                 MOVS            R1, #1
00001248                 STR             R0, [SP,#0x38+var_24]
0000124A                 MOV             R0, 0x1E84EA
00001252                 STR             R3, [SP,#0x38+var_20]
00001254                 STR             R3, [SP,#0x38+var_38]
00001256                 STR             R3, [SP,#0x38+var_34]
00001258                 STR             R0, [SP,#0x38+var_18]
0000125A                 STR             R3, [SP,#0x38+var_30]
0000125C                 ADD             R0, SP, #0x38+var_2C
0000125E                 BLX             _mach_msg
00001262                 ADD             SP, SP, #0x30
00001264                 POP             {R7,PC}
以下是所调用和使用的内容的定义:

typedef struct {
    unsigned char       mig_vers;
    unsigned char       if_vers;
    unsigned char       reserved1;
    unsigned char       mig_encoding;
    unsigned char       int_rep;
    unsigned char       char_rep;
    unsigned char       float_rep;
    unsigned char       reserved2;
} NDR_record_t;
extern NDR_record_t NDR_record;
extern mach_msg_return_t    mach_msg(
                mach_msg_header_t *msg,
                mach_msg_option_t option,
                mach_msg_size_t send_size,
                mach_msg_size_t rcv_size,
                mach_port_name_t rcv_name,
                mach_msg_timeout_t timeout,
                mach_port_name_t notify);

据我所知,堆栈指针被反转为变量的48字节。这48个字节用于额外的3个参数还是全部参数?

在48个字节中,12个用于额外的3个参数,其他用于局部变量。你可以在代码中看到这一点,函数在r0到r3中传递四个参数,在[SP,#0x38+var#u38]中传递另一个参数(如果你做数学运算,它只解析为[SP]),在[SP,#4]中传递另一个参数,在[SP,#8]中传递最后一个参数。

我记得,可以通过寄存器传递的尽可能多的参数(r0-r3或4个字)都是通过寄存器传递的。其余的则通过堆栈传递

unsigned int-fun
unsigned int fun
(
    unsigned int a,
    unsigned int b,
    unsigned int c,
    unsigned int d,
    unsigned int e,
    unsigned int f
)
{
    a+=1;
    a|=b+2;
    a&=c+4;
    a^=d+5;
    a-=e+6;
    a|=~f;
    return(a);
}


00000000 <fun>:
   0:   e2800001    add r0, r0, #1
   4:   e2811002    add r1, r1, #2
   8:   e181c000    orr ip, r1, r0
   c:   e2822004    add r2, r2, #4
  10:   e002100c    and r1, r2, ip
  14:   e59d0000    ldr r0, [sp]
  18:   e2833005    add r3, r3, #5
  1c:   e023c001    eor ip, r3, r1
  20:   e59d1004    ldr r1, [sp, #4]
  24:   e060200c    rsb r2, r0, ip
  28:   e2420006    sub r0, r2, #6
  2c:   e1e03001    mvn r3, r1
  30:   e1800003    orr r0, r0, r3
  34:   e12fff1e    bx  lr
( 无符号整数a, 无符号整数b, 无符号整数c, 无符号整数d, 无符号整数e, 无符号整数f ) { a+=1; a |=b+2; a&=c+4; a^=d+5; a-=e+6; a |=f; 报税表(a); } 00000000 : 0:e2800001加上r0,r0,#1 4:e2811002添加r1,r1,#2 8:e181c000或ip,r1,r0 c:e2822004添加r2、r2、#4 10:e002100c和r1、r2、ip 14:e59d0000 ldr r0[sp] 18:e2833005添加r3,r3,#5 1c:e023c001提高采收率ip,r3,r1 20:e59d1004 ldr r1[sp,#4] 24:e060200c rsb r2,r0,ip 28:e2420006分接头r0,r2,#6 2c:e1e03001 mvn r3,r1 30:e1800003或r0、r0、r3 34:E12FF1E bx lr
前四个按顺序是r0=a、r1=b、r2=c、r3-d,然后按相反顺序推动其余四个,使sp+0为e,sp+4为f


如果你有一个64位整数,那么这将需要两个寄存器,因此你可以使用r0-r3和四个整数,两个整数和一个长整数,或者两个长整数,等等。

那么剩余的参数是从堆栈指针的开始开始的吗?对,这就是
[sp]
的意思。