ARM Assembly-вызывающая функция с более чем 4 аргументами
Я знаю, что при вызове функции в сборке r0 содержит первый аргумент до R3, являющийся четвертым. Я знаю, что когда он выходит за пределы четырех, используется указатель стека, но я не слишком уверен в специфике. 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 аргументов или для всех из них?
3 ответов
из 48 байтов 12 предназначены для дополнительных 3 параметров, а остальные-для локальных переменных. Вы можете увидеть это в коде, где функция передает четыре параметра в r0 через r3, другой в [SP,#0x38+var_38] (который, если вы сделаете математику, разрешится только [sp]), другой в [sp,#4] и последний в [sp,#8].
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
первые четыре-r0 = a, r1 = b, r2 = c, r3 - d, в порядке, а затем остальные толкаются в обратном порядке, так что sp+0-e, а sp+4-f.
Если у вас есть 64-битное целое число, то это займет два регистра, поэтому вы можете использовать r0-r3 с четырьмя входами или двумя входами и длинным длинным или двумя длинными длинными и т. д.
Я помню, столько, сколько может быть передано через регистры (R0-r3 или 4 слова) передаются через регистры. а остальные передаются через стек.