Skip to content

Understanding Assembly

Hon Chen edited this page May 18, 2017 · 12 revisions

x86_64 register calling convention

There are 16 general purpose registers: RAX, RBX, RCX, RDX, RSI, RDI, RSP, RBP and R8 through R15.

When a function is called in x64 assembly. The first six parameters are stored in registers. If there are more than six parameters, then the program's stack is used to pass in additional parameters to the function.

RAX is the designated register for return values from function. When you step-out of a function that returns a value. That value will be available in the RAX register.

Description Register
First Argument RDI
Second Argument RSI
Third Argument RDX
Fourth Argument RCX
Fifth Argument R8
Sixth Argument R9
the return register RAX

An example with NSLog

NSString *name = @"Zoltan";
NSLog(@"Hello world, I am %@. I'm %d, and I live in %@.", name, 30, @"my father's basement");

can be translated to

RDI = @"Hello world, I am %@. I'm %d, and I live in %@.";
RSI = @"Zoltan";
RDX = 30;
RCX = @"my father's basement";
NSLog(RDI, RSI, RDX, RCX);

Objective-C and registers

When Objective-C executes a method call, the compiler will execute a C-function called objc_msgSend and add parameters as follows:

  • The first will be a reference to the object that is to receive the message.
  • The second is the selector, specifying the name of the method being called on the first parameter. Represented as a c-string (char *)
  • Any arguments passed to the ObjC method will be store starting with RDX and so on.
Description Register
Reference to message receiver RDI
Selector of the method RSI
First Argument RDX
Second Argument RCX
Third Argument R8
Fourth Argument R9

An example with NSString

NSString *helloWorldString = [@"Can't Sleep; " stringByAppendingString:@"Clowns will eat me"];

RDI = @"Can't Sleep; "
RSI = "stringByAppendingString:"
RDX = @"Clowns will eat me"
objc_msgSend(@"Can't Sleep; ", "stringByAppendingString:", @"Clowns will eat me")

Swift and registers

Swift and x64 follow the same calling conventions. RDI, RSI, RDX, RCX, R8 and R9 hold your first six parameters. Parameters after the sixth go on the stack.

Two things to consider:

  1. Registers are not available in the Swift debugging context. You have to use the ObjC debugging context to print out registers, expression -l objc -O --
  2. Swift is not as dynamic as Objective-C, it's a good idea to explicitly cast memory addresses to the object you expect it to be.

Clone this wiki locally