-
Notifications
You must be signed in to change notification settings - Fork 0
Understanding Assembly
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);
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 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:
- 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 -- - 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.