Arm Assembly - вызов функции с более чем 4 аргументами - PullRequest
8 голосов
/ 06 ноября 2011

Я знаю, что при вызове функции в сборке 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 ]

6 голосов
/ 06 ноября 2011

Из 48 байтов 12 предназначены для дополнительных 3 параметров, а остальные для локальных переменных. Вы можете увидеть это в коде, где функция передает четыре параметра от r0 до r3, другой в [SP, # 0x38 + var_38] (который, если вы выполняете математические вычисления, разрешает просто [sp]), другой в [sp, # 4 ] и последнее в [sp, # 8].

1 голос
/ 07 ноября 2011
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 с четырьмя или двумя входами, длинным или двумя длинными и т. Д. И т. Д.

0 голосов
/ 06 ноября 2011

я помню, столько, сколько может быть передано через регистры (r0-r3 или 4 слова), передано через регистры. а остальные передаются через стек.

...