Search code examples
iphonecompiler-constructionassemblyarmcalling-convention

Question about Objective C calling convention and argument passing on ARM


I want to know how objective C runtime handle arguments when I call a objective C method like

[NSString stringWithFomat:@"%@, %@", @"Hello", @"World"]

There are three arguments for this objective C call, how does it work compared to typical way on a ARM system. I have known register r0, r1, r2, r3 will hold first 4 arguments, how about there are additional arguments? How does it put them on a stack and pop them later?


Solution

  • For functions that returns a simple type:

    r0 = self (NSString)
    r1 = _cmd (@selector(stringWithFormat:))
    r2 = 1st argument (@"%@, %@")
    r3 = 2nd argument (@"Hello")
    

    then the rest is placed on the stack:

    [sp,#0] = 3rd argument (@"World")
    [sp,#4] = 4th argument (does not exist in your example)
    ...
    

    Of course, "argument" here means a 4-byte object. If the argument has >4 bytes then it will be split out, e.g.

    -[UIView initWithFrame:rect];
    
    r0 = self
    r1 = _cmd
    r2 = rect.origin.x
    r3 = rect.origin.y
    [sp,#0] = rect.size.width
    [sp,#4] = rect.size.height
    

    The returned value (up to 16 bytes) will be placed in r0, r1, r2, r3.


    For functions that returns a struct: r0 is used to store the pointer of the return value.

    NSRange retval = [self rangeOfString:string options:options range:range]
    
    r0 = &retval (of type NSRange*)
    r1 = self
    r2 = _cmd (@selector(rangeOfString:options:range:))
    r3 = string
    [sp,#0] = options
    [sp,#4] = range.location
    [sp,#8] = range.length