2011-11-06 3 views
8

Je sais que lors de l'appel d'une fonction dans l'assemblage, r0 contient le premier argument jusqu'à r3 étant le quatrième. Je sais que quand il dépasse quatre, le pointeur de la pile est utilisé mais je ne suis pas trop sûr des détails. Est-ce que r0-r3 détient encore les quatre premiers et le reste va sur la pile? Je regarde le morceau d'assemblage suivant essayant de comprendre ce qu'il fait pour appeler mach_msg (une fonction avec sept arguments). À l'entrée de ce code, r0 et r1 contiennent les deux argumentsArm Assembly - Fonction d'appel avec plus de 4 arguments

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 
000LDR    R2, [R2] ; _NDR_record 
000LDR    R3, [R2] 
000LDR    R2, [R2,#4] 
000STR    R2, [SP,#0x38+var_10] 
000MOVS   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} 

Voici les définitions pour les choses sont appelées et utilisées:

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); 

D'après ce que je comprends, le pointeur de la pile est inversée 48 octets pour les variables. Est-ce 48 octets pour les 3 arguments supplémentaires ou pour chacun d'eux?

Répondre

6

Parmi les 48 octets, 12 sont pour les 3 paramètres supplémentaires, et les autres sont pour les variables locales. Vous pouvez voir ceci dans le code où la fonction passe quatre paramètres dans r0 à r3, un autre dans [SP, # 0x38 + var_38] (qui si vous faites le calcul mathématique juste [sp]), un autre dans [sp, # 4 ], et le dernier dans [sp, # 8].

+0

donc faire les arguments restants commencent à partir du début du pointeur de pile? – user1000039

+0

À droite, c'est ce que '[sp]' veut dire. –

0

Je me souviens, autant de passages de registres (r0-r3 ou 4 mots) sont possibles via des registres. et le reste est passé à travers la pile.

1
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 

Les quatre premiers sont r0 = a, r1 = b, r2 = c, r3 - d, dans l'ordre, et ensuite le reste est poussé dans l'ordre inverse de sorte que sp + 0 est e et sp + 4 est f.

Si vous avez par exemple un entier de 64 bits alors que prendra deux registres, de sorte que vous pouvez utiliser jusqu'à r0-r3 avec quatre ints ou deux ints et un long, ou deux longs longs, etc.

Questions connexes