banner



What Are The Rsi And Rdi Registers

In this tutorial, you'll look at registers the CPU uses and explore and modify parameters passed into function calls. You'll also larn about common Apple computer architectures and how their registers are used within a function. This is known every bit an architecture's calling convention.

Knowing how assembly works and how a specific compages's calling convention works is an extremely important skill to have. It lets yous observe function parameters you don't have the source lawmaking for and lets you change the parameters passed into a role. In addition, it's sometimes even amend to go to the assembly level because your source code could take different or unknown names for variables you're not aware of.

For case, let'southward say y'all ever wanted to know the second parameter of a office call, regardless of what the parameter's name is. Noesis of assembly gives y'all a bully base layer to dispense and observe parameters in functions.

Assembly 101

Expect, so what's associates once more?

Have y'all ever stopped in a function yous didn't have source code for, and saw an onslaught of memory addresses followed by scary, brusk commands? Did you huddle in a ball and quietly whisper to yourself you lot'll never await at this dense stuff again? Well… that stuff is known as assembly!

Here's a picture of a backtrace in Xcode, which showcases the associates of a function within the Simulator.

Looking at the image above, the assembly tin be broken into several parts. Each line in a associates instruction contains an opcode, which can exist thought of as an extremely elementary instruction for the calculator.

So what does an opcode await like? An opcode is an didactics that performs a simple chore on the calculator. For example, consider the following snippet of assembly:

pushq   %rbx subq    $0x228, %rsp  movq    %rdi, %rbx        

In this block of assembly, y'all see three opcodes, pushq , subq , and movq . Recall of the opcode items as the activity to perform. The things following the opcode are the source and destination labels. That is, these are the items the opcode acts upon.

In the above example, there are several registers, shown as rbx , rsp , rdi , and rbp . The % earlier each tells you this is a register.

In addition, you tin can also find a numeric constant in hexadecimal shown as 0x228 . The $ before this abiding tells you information technology'southward an absolute number.

There'due south no need to know what this code is doing at the moment, since you'll starting time need to learn nearly the registers and calling convention of functions.

Notation: In the above instance, take note there are a agglomeration of %'s and $'s that precede the registers and constants. This is how the disassembler formats the assembly. Withal, there are two chief means that associates tin be showcased. The first is Intel associates, and the 2d is AT & T assembly.

By default, Apple's disassembler tools ship with assembly displayed in the AT&T format, as it is in the instance in a higher place. Although this is a good format to work with, it can admittedly be a fiddling hard on the caput.

x86_64 vs ARM64

As a developer for Apple platforms, there are two primary architectures you'll deal with when learning assembly: x86 _ 64 architecture and ARM64 architecture. x86_64 is the architecture nearly likely used on your macOS reckoner, unless you are running an "ancient" Macintosh.

x86_64 is a 64-flake compages, which means every accost can hold upward to 64 1s or 0s. Alternatively, older Macs use a 32-flake architecture, simply Apple stopped making 32-bit Macs at the end of the 2010'due south. Programs running under macOS are likely to be 64-bit uniform, including programs on the Simulator. That existence said, even if your macOS is x86_64, it tin still run 32-bit programs.

If you accept whatsoever doubt of what hardware architecture you're working with, you tin get your computer's hardware architecture by running the post-obit control in Concluding:

uname -m        

ARM64 architecture is used on mobile devices such as your iPhone where limiting energy consumption is critical.

ARM emphasizes power conservation, and then information technology has a reduced set of opcodes that help facilitate energy consumption over complex assembly instructions. This is good news for yous, considering there are fewer instructions for yous to learn on the ARM architecture.

Here's a screenshot of the aforementioned method shown earlier, except this time in ARM64 assembly on an iPhone seven:

in many of their devices, but accept since moved to 64-bit ARM processors. 32-bit devices are almost obsolete as Apple tree has phased them out through various iOS versions. For case, the iPhone 4s is a 32-bit device which is not supported in iOS ten. All that remains in the 32-bit iPhone lineup is the iPhone 5, which iOS 10 does support.

Interestingly, all Apple Watch devices are currently 32-flake. This is probable because 32-scrap ARM CPUs typically draw less power than their 64-fleck cousins. This is really of import for the watch as the battery is tiny.

Since it'south best to focus on what yous'll need for the hereafter, Advanced Apple Debugging & Reverse Engineering volition focus primarily on 64-chip assembly for both architectures. In improver, you'll outset learning x86_64 assembly offset and then transition to learning ARM64 assembly so y'all don't get confused. Well, not likewise confused.

x86_64 Register Calling Convention

Your CPU uses a set of registers in lodge to dispense data in your running program. These are storage holders, merely similar the RAM in your computer. All the same they're located on the CPU itself very close to the parts of the CPU that need them. And then these parts of the CPU can access these registers incredibly quickly.

Most instructions involve one or more registers and perform operations such every bit writing the contents of a register to retentivity, reading the contents of retentiveness to a register or performing arithmetic operations (add together, decrease, etc.) on 2 registers.

In x64 (from hither on out, x64 is an abbreviation for x86_64), there are 16 full general purpose registers used by the machine to manipulate data.

These registers are RAX, RBX, RCX, RDX, RDI, RSI, RSP, RBP and R8 through R15. These names will not mean much to you now, but you'll explore the importance of each register before long.

When you telephone call a role in x64, the manner and use of the registers follows a very specific convention. This dictates where the parameters to the role should go and where the return value from the part will exist when the role finishes. This is important and so code compiled with ane compiler can be used with code compiled with another compiler.

For instance, take a expect at this uncomplicated Objective-C lawmaking:

NSString *proper noun = @"Zoltan"; NSLog(@"Hullo world, I am %@. I'm %d, and I live in %@.", proper name, 30, @"my male parent's basement");        

There are four parameters passed into the NSLog function call. Some of these values are passed equally-is, while one parameter is stored in a local variable, then referenced as a parameter in the function. However, when viewing code through assembly, the reckoner doesn't care well-nigh names for variables; it merely cares about locations in retentiveness.

The following registers are used every bit parameters when a function is called in x64 assembly. Try and commit these to memory, as you'll use these frequently in the future:

  • First Argument: RDI
  • 2nd Argument: RSI
  • Third Argument: RDX
  • Quaternary Statement: RCX
  • Fifth Argument: R8
  • Sixth Argument: R9

If there are more than six parameters, so the program'due south stack is used to pass in additional parameters to the function.

Going back to that uncomplicated Objective-C code, you tin can re-imagine the registers being passed similar the following pseudo-code:

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

As shortly as the NSLog office starts, the given registers volition contain the appropriate values as shown above.

Still, as soon as the office prologue (the offset section of a function that prepares the stack and registers) finishes executing, the values in these registers will likely change. The generated assembly volition likely overwrite the values stored in these registers, or but simply discard these references when the lawmaking has no more than need of them.

This ways as before long as y'all leave the offset of a role (through stepping over, stepping in, or stepping out), you can no longer assume these registers will hold the expected values you want to observe, unless you actually look at the assembly code to see what information technology'southward doing.

This calling convention heavily influences your debugging (and breakpoint) strategy. If y'all were to automate any type of breaking and exploring, you would have to cease at the start of a function phone call in order to inspect or modify the parameters without having to really swoop into the assembly.

Objective-C and Registers

Registers use a specific calling convention. Y'all can have that same knowledge and apply it to other languages every bit well.

When Objective-C executes a method, a special C function is executed named objc_msgSend . There's actually several different types of these functions, but more on that after. This is the heart of message acceleration. Every bit the first parameter, objc_msgSend takes the reference of the object upon which the message is being sent. This is followed past a selector, which is simply just a char * specifying the name of the method beingness chosen on the object. Finally, objc_msgSend takes a variable amount of arguments within the function if the selector specifies there should be parameters.

Let's look at a physical case of this in an iOS context:

[UIApplication sharedApplication];        

The compiler will take this code and create the post-obit pseudocode:

id UIApplicationClass = [UIApplication class]; objc_msgSend(UIApplicationClass, "sharedApplication");        

The first parameter is a reference to the UIApplication class, followed by the sharedApplication selector. An like shooting fish in a barrel way to tell if in that location are any parameters is to merely check for colons in the Objective-C selector. Each colon volition represent a parameter in a Selector.

Here'south another Objective-C instance:

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

The compiler will create the post-obit (shown below in pseudocode):

NSString *helloWorldString;  helloWorldString = objc_msgSend(@"Can't Sleep; ", "stringByAppendingString:", @"Clowns will eat me");        

The showtime argument is an instance of an NSString (@"Tin can't Sleep; "), followed by the selector, followed by a parameter which is as well an NSString case.

Using this knowledge of objc_msgSend, you can use the registers in x64 to help explore content, which you'll do very shortly.

Putting Theory to Practice

You tin can download the starter project for this tutorial here.

For this section, you'll exist using a project supplied in this tutorial'south resource bundle called Registers.

Open this project up through Xcode and give it a run.

This is a rather unproblematic application which merely displays the contents of some x64 registers. Information technology'due south of import to note that this application can't display the values of registers at any given moment, information technology tin can simply brandish the values of registers during a specific function telephone call. This means that you won't see too many changes to the values of these registers since they'll probable have the same (or similar) value when the function to catch the register values is chosen.

At present that y'all've got an agreement of the functionality behind the Registers macOS application, create a symbolic breakpoint for NSViewController's viewDidLoad method. Remember to use "NS" instead of "UI", since you're working on a Cocoa application.

Build and rerun the application. Once the debugger has stopped, type the following into the LLDB console:

(lldb) register read        

This volition list all of the main registers at the paused state of execution. Notwithstanding, this is too much data. Yous should selectively print out registers and treat them as Objective-C objects instead.

If y'all recall, -[NSViewController viewDidLoad] will exist translated into the following assembly pseudocode:

RDI = UIViewControllerInstance  RSI = "viewDidLoad" objc_msgSend(RDI, RSI)        

With the x64 calling convention in heed, and knowing how objc_msgSend works, you lot tin can find the specific NSViewController that is being loaded.

Type the following into the LLDB console:

(lldb) po $rdi        

You'll get output like to the following:

<Registers.ViewController: 0x6080000c13b0>        

This will dump out the NSViewController reference held in the RDI register, which as you lot at present know, is the location of the first argument to the method.

In LLDB, information technology'due south important to prefix registers with the $ character, then LLDB knows you want the value of a annals and not a variable related to your scope in the source lawmaking. Yes, that's dissimilar than the associates you lot see in the disassembly view! Annoying, eh?

Annotation: The observant among you might notice whenever you stop on an Objective-C method, you'll never run into the objc_msgSend in the LLDB backtrace. This is because the objc\_msgSend family unit of functions perfoms a jmp , or leap opcode command in assembly. This means that objc\_msgSend acts as a trampoline function, and once the Objective-C code starts executing, all stack trace history of objc\_msgSend will exist gone. This is an optimization known as tail call optimization.

Try printing out the RSI register, which will hopefully contain the selector that was called. Type the following into the LLDB panel:

(lldb) po $rsi        

Unfortunately, you lot'll get garbage output that looks something like this:

140735181830794        

Why is this?

An Objective-C selector is basically but a char *. This means, like all C types, LLDB does not know how to format this data. Every bit a result, yous must explicitly cast this reference to the data type yous desire.

Endeavor casting it to the right blazon:

(lldb) po (char *)$rsi        

Y'all'll at present get the expected:

"viewDidLoad"        

Of form, yous can also cast information technology to the Selector type to produce the same upshot:

(lldb) po (SEL)$rsi        

Now, it'due south time to explore an Objective-C method with arguments. Since y'all've stopped on viewDidLoad, you can safely assume the NSView instance has loaded. A method of interest is the mouseUp: selector implemented by NSView's parent class, NSResponder.

In LLDB, create a breakpoint on NSResponder'southward mouseUp: selector and resume execution. If you can't call back how to do that, hither are the commands you need:

(lldb) b -[NSResponder mouseUp:] (lldb) continue        

Now, click on the application's window. Make certain to click on the outside of the NSScrollView equally it will gobble up your click and the -[NSResponder mouseUp:] breakpoint will non get hitting.

As soon as you permit go of the mouse or the trackpad, LLDB will cease on the mouseUp: breakpoint. Print out the reference of the NSResponder past typing the post-obit into the LLDB console:

(lldb) po $rdi        

You'll get something similar to the post-obit:

<NSView: 0x608000120140>        

Nevertheless, in that location's something interesting with the selector. At that place'southward a colon in it, meaning there'southward an statement to explore! Type the following into the LLDB console:

(lldb) po $rdx        

Yous'll get the clarification of the NSEvent:

NSEvent: type=LMouseUp loc=(351.672,137.914) fourth dimension=175929.four flags=0 win=0x6100001e0400 winNum=8622 ctxt=0x0 evNum=10956 click=i buttonNumber=0 pressure level=0 deviceID:0x300000014400000 subtype=NSEventSubtypeTouch        

How can you tell it's an NSEvent? Well, yous can either wait online for documentation on -[NSResponder mouseUp:] or, you can only utilize Objective-C to become the type:

(lldb) po [$rdx class]        

Pretty cool, eh?

Sometimes it's useful to use registers and breakpoints in order to get a reference to an object you know is alive in retentiveness.

For instance, what if you lot wanted to change the front NSWindow to red, but you had no reference to this view in your code, and yous didn't want to recompile with whatsoever code changes? You tin simply create a breakpoint you tin easily trip, go the reference from the annals and dispense the case of the object as you please. You'll try changing the master window to red now.

Annotation: Even though NSResponder implements mouseDown:, NSWindow overrides this method since it's a subclass of NSResponder. You can dump all classes that implement mouseDown: and figure out which of those classes inherit from NSResponder to decide if the method is overridden without having access to the source code. An example of dumping all the Objective-C classes that implement mouseDown: is epitome lookup -rn '\ mouseDown:'

First remove whatever previous breakpoints using the LLDB console:

(lldb) breakpoint delete About to delete all breakpoints, do you desire to do that?: [Y/n]        

Then type the following into the LLDB console:

(lldb) breakpoint fix -o -Southward "-[NSWindow mouseDown:]" (lldb) go on        

This sets a breakpoint which will fire just one time — a i-shot breakpoint.

Tap on the awarding. Immediately after tapping, the breakpoint should trip. And then blazon the following into the LLDB console:

(lldb) po [$rdi setBackgroundColor:[NSColor redColor]] (lldb) go along        

Upon resuming, the NSWindow will alter to cherry-red!

Swift and Registers

When exploring registers in Swift, you lot'll hit two hurdles that make assembly debugging harder than information technology is in Objective-C.

  1. First, registers are non available in the Swift debugging context. This means you have to go any data you desire and so employ the Objective-C debugging context to print out the registers passed into the Swift role. Remember that y'all can apply the expression -l objc -O -- command, or alternatively employ the cpo custom command found in Chapter 8 of the book, "Persisting and Customizing Commands". Fortunately, the annals read command is available in the Swift context.
  2. 2nd, Swift is not as dynamic as Objective-C. In fact, information technology'due south sometimes all-time to assume that Swift is like C, except with a very, very cranky and bossy compiler. If yous have a retentiveness address, you demand to explicitly cast information technology to the object you look it to exist; otherwise, the Swift debugging context has no clue how to interpret a memory address.

That beingness said, the same annals calling convention is used in Swift. However, there's one very of import divergence. When Swift calls a function, information technology has no need to use objc_msgSend, unless of grade you mark up a method to use dynamic . This means when Swift calls a function, the previously used RSI register assigned to the selector volition actually contain the function'due south 2d parameter.

Enough theory — fourth dimension to see this in action.

In the Registers project, navigate to ViewController.swift and add the following function to the class:

func executeLotsOfArguments(one: Int, 2: Int, iii: Int,                             four: Int, 5: Int, six: Int,                             seven: Int, eight: Int, ix: Int,                             ten: Int) {     print("arguments are: \(one), \(ii), \(three),           \(four), \(five), \(six), \(seven),           \(eight), \(nine), \(10)") }        

Now, in viewDidLoad, call this function with the appropriate arguments:

override func viewDidLoad() {   super.viewDidLoad()   self.executeLotsOfArguments(ane: i, ii: 2, three: 3, four: 4,                               five: 5, half-dozen: 6, seven: 7,                               viii: eight, nine: 9, ten: ten) }        

Put a breakpoint on the very same line as of the declaration of executeLotsOfArguments so the debugger will stop at the very start of the function. This is important, or else the registers might get clobbered if the function is really executing.

Then remove the symbolic breakpoint y'all fix on -[NSViewController viewDidLoad].

Build and run the app, and so wait for the executeLotsOfArguments breakpoint to stop execution.

Once more, a good mode to start investigating is to dump the list registers. In LLDB, blazon the following:

(lldb) register read -f d        

This volition dump the registers and display the format in decimal by using the -f d option. The output will await like to this:

General Purpose Registers:        rax = seven        rbx = ix        rcx = 4        rdx = iii        rdi = 1        rsi = ii        rbp = 140734799801424        rsp = 140734799801264         r8 = 5         r9 = vi        r10 = 10        r11 = 8        r12 = 107202385676032        r13 = 106652628550688        r14 = 10        r15 = 4298620128  libswiftCore.dylib`swift_isaMask        rip = 4294972615  Registers`Registers.ViewController.viewDidLoad () -> () + 167 at ViewController.swift:16     rflags = 518         cs = 43         fs = 0         gs = 0        

Every bit you lot can see, the registers follow the x64 calling convention. RDI, RSI, RDX, RCX, R8 and R9 concur your starting time 6 parameters.

You may also notice other parameters are stored in some of the other registers. While this is true, it'due south simply a leftover from the code that sets up the stack for the remaining parameters. Remember, parameters after the sixth one go on the stack.

RAX, the Return Annals

But wait — there's more! So far, you lot've learned how vi registers are called in a function, but what about return values?

Fortunately, there is only one designated register for render values from functions: RAX . Go back to executeLotsOfArguments and modify the function to return a String, like so:

func executeLotsOfArguments(one: Int, 2: Int, iii: Int,                             iv: Int, five: Int, six: Int,                             seven: Int, eight: Int, 9: Int,                             ten: Int) -> String {     print("arguments are: \(i), \(2), \(three), \(iv),           \(five), \(six), \(seven), \(8), \(nine), \(ten)")     return "Mom, what happened to the cat?" }        

In viewDidLoad, modify the function phone call to receive and ignore the String value.

override func viewDidLoad() {     super.viewDidLoad()     let _ = self.executeLotsOfArguments(one: 1, two: ii,           three: three, four: 4, five: 5, six: 6, seven: vii,           eight: eight, ix: 9, ten: ten) }        

Create a breakpoint somewhere in executeLotsOfArguments. Build and run again, and expect for execution to stop in the office. Next, blazon the following into the LLDB console:

(lldb) cease        

This will end executing the current office and intermission the debugger again. At this indicate, the return value from the role should be in RAX. Type the following into LLDB:

(lldb) annals read rax        

You'll go something similar to the post-obit:

rax = 0x0000000100003760  "Mom, what happened to the cat?"        

Boom! Your return value!

Knowledge of the return value in RAX is extremely of import as it will form the foundation of debugging scripts you'll write in later sections.

Irresolute Values in Registers

In guild to solidify your agreement of registers, you'll modify registers in an already-compiled application.

Close Xcode and the Registers project. Open a Terminal window and launch the iPhone 7 Simulator. Do this by typing the following:

xcrun simctl listing        

You'll see a long list of devices. Search for the latest iOS version for which you have a simulator installed. Underneath that department, detect the iPhone vii device. It will expect something like this:

iPhone 7 (269B10E1-15BE-40B4-AD24-B6EED125BC28) (Shutdown)        

The UUID is what yous're after. Use that to open up the iOS Simulator by typing the post-obit, replacing your UUID every bit advisable:

open /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app --args -CurrentDeviceUDID 269B10E1-15BE-40B4-AD24-B6EED125BC28        

Make sure the simulator is launched and is sitting on the home screen. You tin get to the domicile screen past pressing Control + Shift + H. Once your simulator is set, head over to the Terminal window and adhere LLDB to the SpringBoard application:

lldb -n SpringBoard        

This attaches LLDB to the SpringBoard instance running on the iOS Simulator! SpringBoard is the plan that controls the home screen on iOS.

Once attached, blazon the following into LLDB:

(lldb) p/x @"Yay! Debugging"        

Yous should get some output like to the following:

(__NSCFString *) $iii = 0x0000618000644080 @"Yay! Debugging!"        

Have a note of the retention reference of this newly created NSString example every bit yous'll apply information technology soon. Now, create a breakpoint on UILabel'south setText: method in LLDB:

(lldb) b -[UILabel setText:]        

Next, type the following in LLDB:

(lldb) breakpoint command add        

LLDB volition spew some output and go into multi-line edit way. This command lets you add extra commands to execute when the breakpoint you just added is hit. Blazon the following, replacing the retentivity address with the accost of your NSString from above:

> po $rdx = 0x0000618000644080 > go along > Done        

Take a step back and review what you've simply done. You've created a breakpoint on UILabel's setText: method. Whenever this method gets hit, you're replacing what's in RDX — the 3rd parameter — with a dissimilar NSString instance that says Yay ! Debugging !.

Resume the debugger by using the continue control:

(lldb) continue        

Try exploring the SpringBoard Simulator app and see what content has changed. Swipe up from the bottom to bring up the Control Eye, and notice the changes:

Try exploring other areas where modal presentations tin occur, equally this will likely result in a new UIViewController (and all of its subviews) existence lazily loaded, causing the breakpoint action to exist hit.

Although this might seem like a cool gimmicky programming trick, it provides an insightful wait into how a express knowledge of registers and assembly can produce big changes in applications you don't have the source for.

This is likewise useful from a debugging standpoint, as you can quickly visually verify where the -[UILabel setText:] is executed within the SpringBoard application and run breakpoint conditions to discover the exact line of lawmaking that sets a particular UILabel'south text.

To continue this thought, any UILabel instances whose text did not change as well tells you something. For example, the UIButtons whose text didn't change to Yay! Debugging! speaks for itself. Perhaps the UILabel's setText: was called at an earlier time? Or perchance the developers of the SpringBoard application chose to utilize setAttributedText: instead? Or maybe they're using a private method that is not publicly available to third-party developers?

As you tin can meet, using and manipulating registers tin can give you a lot of insight into how an application functions. :]

Where to Go From Here?

Whew! That was a long one, wasn't information technology? Sit down back and take a pause with your favorite form of liquid; you've earned it.

You tin download the completed project from this tutorial here.

So what did y'all larn?

  • Architectures define a calling convention which dictates where parameters to a function and its return value are stored.
  • In Objective-C, the RDI register is the reference of the calling NSObject, RSI is the Selector, RDX is the first parameter and so on.
  • In Swift, RDI is the outset argument, RSI is the second parameter, and then on provided that the Swift method isn't using dynamic dispatch.
  • The RAX register is used for return values in functions regardless of whether you're working with Objective-C or Swift.
  • Brand sure yous use the Objective-C context when printing registers with $.

There'southward a lot you tin can do with registers. Try exploring apps y'all don't accept the source code for; it's a lot of fun and will build a proficient foundation for tackling tough debugging problems.

Attempt attaching to an application on the iOS Simulator and map out the UIViewControllersouthward equally they announced using assembly, a smart breakpoint, and a breakpoint command.

If you enjoyed what yous learned in the tutorial, why not check out the complete Avant-garde Apple Debugging & Opposite Engineering volume, available on our store?

Hither's a taste of what'due south in the volume:

  • Getting Started: Learn your style around LLDB and its extensive list of subcommands and options.
  • Python Power: Use LLDB'south Python module to create powerful, custom debugging commands to introspect and augment existing programs.
  • Agreement Assembly: Truly empathise how lawmaking works at an assembler-level and how y'all can explore code in memory.
  • Ptrace and Friends: Learn how to leverage ptrace, dlopen and dlsym to claw into C and Swift functions to explore lawmaking that you don't take the source for.
  • Script Bridging: Extend the debugger to make information technology do about anything you lot want, and learn how to laissez passer in options or arguments to your debugging scripts.
  • DTrace: Dig deep and hook into a office with a DTrace probe to query a massive amount of process information.
  • …and more!

By the end of this book, you'll have the tools and cognition to answer fifty-fifty the almost obscure question virtually your code — or someone else's.

To celebrate the launch of the book, information technology's currently on auction for $44.99 — that's a $10 discount off the cover price! Only don't wait as well long, as the launch deal is only on until Friday, May 19th.

If yous have any questions or comments on this tutorial, feel free to join the give-and-take below!

What Are The Rsi And Rdi Registers,

Source: https://www.raywenderlich.com/615-assembly-register-calling-convention-tutorial

Posted by: hayeksulow1964.blogspot.com

Related Posts

0 Response to "What Are The Rsi And Rdi Registers"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel