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