banner



How To Add Registers In Assembly

In this tutorial, yous'll look at registers the CPU uses and explore and modify parameters passed into role calls. You'll likewise learn virtually mutual Apple computer architectures and how their registers are used within a function. This is known every bit an compages'south calling convention.

Knowing how assembly works and how a specific architecture's calling convention works is an extremely important skill to have. It lets you observe role parameters you lot don't have the source code for and lets you lot alter the parameters passed into a function. In addition, it'southward sometimes fifty-fifty amend to become to the assembly level because your source lawmaking could accept different or unknown names for variables you're not aware of.

For example, let's say y'all always wanted to know the second parameter of a part call, regardless of what the parameter'southward proper noun is. Knowledge of assembly gives you a great base of operations layer to dispense and observe parameters in functions.

Assembly 101

Await, so what'south assembly again?

Have you ever stopped in a office you didn't take 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'll never look at this dumbo stuff again? Well… that stuff is known as assembly!

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

Looking at the image higher up, the associates tin be cleaved into several parts. Each line in a assembly instruction contains an opcode, which can be thought of as an extremely unproblematic instruction for the computer.

So what does an opcode look like? An opcode is an instruction that performs a simple task on the computer. For example, consider the post-obit snippet of assembly:

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

In this block of assembly, you come across three opcodes, pushq , subq , and movq . Think 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 every bit rbx , rsp , rdi , and rbp . The % before each tells you this is a register.

In addition, you lot can also notice a numeric abiding in hexadecimal shown as 0x228 . The $ before this constant tells you it's an absolute number.

In that location'southward no need to know what this lawmaking is doing at the moment, since yous'll get-go need to learn virtually the registers and calling convention of functions.

Note: In the above case, take note there are a agglomeration of %'s and $'due south that precede the registers and constants. This is how the disassembler formats the assembly. Nevertheless, there are 2 main ways that assembly tin can be showcased. The first is Intel associates, and the second is AT & T associates.

By default, Apple's disassembler tools ship with assembly displayed in the AT&T format, as it is in the example above. Although this is a good format to work with, it tin can absolutely exist a fiddling hard on the head.

x86_64 vs ARM64

Equally a developer for Apple platforms, at that place are two primary architectures you'll bargain with when learning assembly: x86 _ 64 architecture and ARM64 architecture. x86_64 is the architecture nigh likely used on your macOS computer, unless you are running an "ancient" Macintosh.

x86_64 is a 64-bit compages, which ways every accost can hold upwardly to 64 1s or 0s. Alternatively, older Macs use a 32-bit architecture, just Apple tree stopped making 32-bit Macs at the terminate of the 2010's. Programs running under macOS are likely to exist 64-flake compatible, including programs on the Simulator. That being said, even if your macOS is x86_64, it tin can nevertheless run 32-bit programs.

If you lot have any dubiousness of what hardware compages you're working with, you tin can go your estimator's hardware architecture by running the following command in Terminal:

uname -thousand        

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

ARM emphasizes ability conservation, and so information technology has a reduced fix of opcodes that assist facilitate energy consumption over complex assembly instructions. This is skilful news for you, because there are fewer instructions for yous to larn on the ARM architecture.

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

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

Interestingly, all Apple tree Watch devices are currently 32-bit. This is likely considering 32-scrap ARM CPUs typically draw less power than their 64-flake cousins. This is really important for the sentry every bit the battery is tiny.

Since it's best to focus on what you'll demand for the future, Advanced Apple tree Debugging & Contrary Technology volition focus primarily on 64-flake assembly for both architectures. In addition, you'll start learning x86_64 assembly first and and so transition to learning ARM64 assembly then you lot don't become confused. Well, non too dislocated.

x86_64 Register Calling Convention

Your CPU uses a set of registers in order to manipulate information in your running program. These are storage holders, just like the RAM in your estimator. However they're located on the CPU itself very close to the parts of the CPU that need them. So these parts of the CPU can access these registers incredibly quickly.

Most instructions involve one or more registers and perform operations such as writing the contents of a register to memory, reading the contents of memory to a register or performing arithmetics operations (add together, subtract, etc.) on two registers.

In x64 (from here on out, x64 is an abridgement for x86_64), in that location are xvi general purpose registers used by the motorcar to dispense 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, simply you lot'll explore the importance of each register shortly.

When you phone call a office in x64, the manner and apply 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 office volition be when the office finishes. This is important so code compiled with one compiler can be used with code compiled with another compiler.

For instance, have a expect at this simple Objective-C code:

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

There are four parameters passed into the NSLog function phone call. Some of these values are passed as-is, while i parameter is stored in a local variable, then referenced as a parameter in the function. Nonetheless, when viewing code through associates, the computer doesn't care most names for variables; it only cares about locations in memory.

The following registers are used as parameters when a office is called in x64 assembly. Try and commit these to retentivity, as you'll utilise these often in the future:

  • Beginning Argument: RDI
  • Second Argument: RSI
  • 3rd Argument: RDX
  • Fourth Argument: RCX
  • Fifth Argument: R8
  • Sixth Argument: R9

If there are more than six parameters, and then the program's stack is used to laissez passer in additional parameters to the part.

Going dorsum to that simple Objective-C code, you lot tin re-imagine the registers beingness passed like the post-obit pseudo-code:

RDI = @"How-do-you-do earth, I am %@. I'm %d, and I live in %@."; RSI = @"Zoltan"; RDX = 30; RCX = @"my father'south basement"; NSLog(RDI, RSI, RDX, RCX);        

As soon equally the NSLog role starts, the given registers will contain the appropriate values every bit shown above.

However, as soon as the function prologue (the beginning section of a role 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 code has no more need of them.

This means as shortly as you lot exit the start of a function (through stepping over, stepping in, or stepping out), you can no longer assume these registers will agree the expected values you want to find, unless you actually look at the assembly lawmaking to run across what it's doing.

This calling convention heavily influences your debugging (and breakpoint) strategy. If you were to automate any type of breaking and exploring, you would take to stop at the outset of a function phone call in social club to audit or modify the parameters without having to really dive into the assembly.

Objective-C and Registers

Registers use a specific calling convention. You tin can take that same knowledge and use it to other languages likewise.

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

Permit's look at a concrete example of this in an iOS context:

[UIApplication sharedApplication];        

The compiler volition have this code and create the following pseudocode:

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

The first parameter is a reference to the UIApplication course, followed by the sharedApplication selector. An easy way to tell if there are any parameters is to but check for colons in the Objective-C selector. Each colon will correspond a parameter in a Selector.

Here'south some other Objective-C instance:

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

The compiler volition create the following (shown below in pseudocode):

NSString *helloWorldString;  helloWorldString = objc_msgSend(@"Tin can't Sleep; ", "stringByAppendingString:", @"Clowns will swallow me");        

The showtime argument is an instance of an NSString (@"Can't Sleep; "), followed by the selector, followed by a parameter which is also an NSString instance.

Using this noesis of objc_msgSend, you can employ the registers in x64 to assist explore content, which you'll practice very before long.

Putting Theory to Practise

Y'all can download the starter project for this tutorial hither.

For this section, y'all'll be using a project supplied in this tutorial's resource bundle chosen Registers.

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

This is a rather simple awarding which merely displays the contents of some x64 registers. It'south important to notation that this awarding can't display the values of registers at whatsoever given moment, it can only display the values of registers during a specific function call. This means that you won't see likewise many changes to the values of these registers since they'll likely have the same (or similar) value when the function to grab the register values is chosen.

At present that you've got an understanding of the functionality backside 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 awarding. Once the debugger has stopped, type the following into the LLDB console:

(lldb) register read        

This will list all of the main registers at the paused state of execution. However, this is too much information. You should selectively print out registers and treat them as Objective-C objects instead.

If you remember, -[NSViewController viewDidLoad] will be translated into the following assembly pseudocode:

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

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

Type the following into the LLDB panel:

(lldb) po $rdi        

Yous'll get output similar to the post-obit:

<Registers.ViewController: 0x6080000c13b0>        

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

In LLDB, it's of import to prefix registers with the $ character, so LLDB knows yous want the value of a register and not a variable related to your scope in the source code. Yes, that's different than the associates y'all meet in the disassembly view! Annoying, eh?

Note: The observant among you might detect whenever you stop on an Objective-C method, you lot'll never see the objc_msgSend in the LLDB backtrace. This is because the objc\_msgSend family of functions perfoms a jmp , or jump opcode command in associates. This means that objc\_msgSend acts every bit a trampoline function, and once the Objective-C code starts executing, all stack trace history of objc\_msgSend will be gone. This is an optimization known as tail call optimization.

Try press out the RSI annals, which will hopefully contain the selector that was called. Type the post-obit into the LLDB console:

(lldb) po $rsi        

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

140735181830794        

Why is this?

An Objective-C selector is basically only a char *. This means, like all C types, LLDB does not know how to format this data. As a result, y'all must explicitly cast this reference to the data type you desire.

Try casting it to the correct blazon:

(lldb) po (char *)$rsi        

You lot'll now go the expected:

"viewDidLoad"        

Of course, y'all tin also cast it to the Selector type to produce the aforementioned result:

(lldb) po (SEL)$rsi        

Now, it's time to explore an Objective-C method with arguments. Since you've stopped on viewDidLoad, you lot can safely assume the NSView case has loaded. A method of involvement is the mouseUp: selector implemented by NSView's parent course, NSResponder.

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

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

At present, click on the awarding'south window. Make sure to click on the outside of the NSScrollView equally it will gobble up your click and the -[NSResponder mouseUp:] breakpoint will not get hit.

As presently as y'all let become of the mouse or the trackpad, LLDB will stop on the mouseUp: breakpoint. Print out the reference of the NSResponder by typing the post-obit into the LLDB console:

(lldb) po $rdi        

You lot'll get something similar to the following:

<NSView: 0x608000120140>        

Nonetheless, there's something interesting with the selector. There's a colon in it, pregnant in that location'southward an argument to explore! Type the following into the LLDB console:

(lldb) po $rdx        

You lot'll get the description of the NSEvent:

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

How can you tell it'due south an NSEvent? Well, you lot can either look online for documentation on -[NSResponder mouseUp:] or, you can simply use Objective-C to get the type:

(lldb) po [$rdx class]        

Pretty cool, eh?

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

For example, what if y'all wanted to change the front NSWindow to red, merely you lot had no reference to this view in your lawmaking, and you didn't want to recompile with any code changes? You tin can just create a breakpoint you can easily trip, get the reference from the register and manipulate the example of the object as you delight. You'll effort irresolute the principal window to ruby at present.

Notation: 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 determine 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 image lookup -rn '\ mouseDown:'

Kickoff remove any previous breakpoints using the LLDB console:

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

Then type the following into the LLDB console:

(lldb) breakpoint set -o -S "-[NSWindow mouseDown:]" (lldb) keep        

This sets a breakpoint which will burn only once — a one-shot breakpoint.

Tap on the application. Immediately afterward tapping, the breakpoint should trip. Then type the post-obit into the LLDB panel:

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

Upon resuming, the NSWindow will change to red!

Swift and Registers

When exploring registers in Swift, you'll hit two hurdles that brand assembly debugging harder than it is in Objective-C.

  1. First, registers are not bachelor in the Swift debugging context. This ways you take to get whatever data you want and and then utilize the Objective-C debugging context to print out the registers passed into the Swift part. Remember that you can utilize the expression -l objc -O -- command, or alternatively apply the cpo custom command found in Chapter viii of the book, "Persisting and Customizing Commands". Fortunately, the register read command is available in the Swift context.
  2. 2d, Swift is not equally dynamic as Objective-C. In fact, it'southward sometimes best to assume that Swift is like C, except with a very, very cranky and bossy compiler. If you have a retention address, yous demand to explicitly bandage it to the object you look it to be; otherwise, the Swift debugging context has no clue how to translate a retentivity address.

That being said, the same register calling convention is used in Swift. However, there's 1 very important divergence. When Swift calls a function, it has no demand to apply objc_msgSend, unless of course you mark upwardly a method to use dynamic . This ways when Swift calls a function, the previously used RSI annals assigned to the selector volition actually contain the part's second parameter.

Enough theory — time to come across this in action.

In the Registers project, navigate to ViewController.swift and add the post-obit office to the class:

func executeLotsOfArguments(1: Int, two: Int, three: Int,                             iv: Int, v: Int, six: Int,                             vii: Int, 8: Int, nine: Int,                             x: Int) {     print("arguments are: \(ane), \(2), \(3),           \(four), \(five), \(six), \(seven),           \(8), \(9), \(ten)") }        

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

override func viewDidLoad() {   super.viewDidLoad()   self.executeLotsOfArguments(one: 1, two: 2, iii: 3, four: iv,                               5: five, 6: 6, seven: vii,                               viii: eight, ix: 9, x: 10) }        

Put a breakpoint on the very same line as of the annunciation of executeLotsOfArguments then the debugger will stop at the very beginning of the part. This is important, or else the registers might go clobbered if the office is really executing.

Then remove the symbolic breakpoint you set on -[NSViewController viewDidLoad].

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

Again, a proficient way to start investigating is to dump the list registers. In LLDB, type the following:

(lldb) register read -f d        

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

General Purpose Registers:        rax = seven        rbx = nine        rcx = 4        rdx = 3        rdi = 1        rsi = ii        rbp = 140734799801424        rsp = 140734799801264         r8 = 5         r9 = 6        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:sixteen     rflags = 518         cs = 43         fs = 0         gs = 0        

As yous tin see, the registers follow the x64 calling convention. RDI, RSI, RDX, RCX, R8 and R9 concord your first six parameters.

You may also notice other parameters are stored in some of the other registers. While this is truthful, it'south only a leftover from the lawmaking that sets up the stack for the remaining parameters. Recall, parameters later on the sixth one proceed the stack.

RAX, the Return Annals

But wait — there'south more! So far, y'all've learned how 6 registers are called in a role, only what about return values?

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

func executeLotsOfArguments(one: Int, two: Int, three: Int,                             4: Int, five: Int, six: Int,                             seven: Int, eight: Int, 9: Int,                             10: Int) -> String {     impress("arguments are: \(one), \(two), \(three), \(four),           \(five), \(six), \(seven), \(eight), \(ix), \(ten)")     return "Mom, what happened to the cat?" }        

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

override func viewDidLoad() {     super.viewDidLoad()     let _ = self.executeLotsOfArguments(one: 1, two: ii,           three: 3, four: four, five: 5, six: 6, 7: seven,           eight: 8, nine: nine, ten: 10) }        

Create a breakpoint somewhere in executeLotsOfArguments. Build and run again, and wait for execution to stop in the function. Side by side, type the following into the LLDB console:

(lldb) finish        

This volition finish executing the current function and interruption the debugger again. At this point, the return value from the function should be in RAX. Type the post-obit into LLDB:

(lldb) annals read rax        

You'll go something similar to the following:

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

Boom! Your return value!

Knowledge of the return value in RAX is extremely important as it will class the foundation of debugging scripts you'll write in after sections.

Changing Values in Registers

In lodge to solidify your understanding of registers, you'll alter registers in an already-compiled application.

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

xcrun simctl list        

You lot'll see a long listing of devices. Search for the latest iOS version for which you have a simulator installed. Underneath that section, detect the iPhone seven device. It will look something similar this:

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

The UUID is what you're later on. Use that to open the iOS Simulator past typing the following, replacing your UUID equally appropriate:

open up /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 can go to the habitation screen by pressing Command + Shift + H. One time your simulator is prepare upwards, 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 programme that controls the home screen on iOS.

Once attached, type the post-obit into LLDB:

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

Y'all should get some output similar to the following:

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

Have a note of the memory reference of this newly created NSString case as you'll employ it soon. At present, create a breakpoint on UILabel'southward setText: method in LLDB:

(lldb) b -[UILabel setText:]        

Adjacent, type the following in LLDB:

(lldb) breakpoint command add        

LLDB volition spew some output and get into multi-line edit mode. This control lets you lot add extra commands to execute when the breakpoint you only added is hitting. Type the post-obit, replacing the memory address with the accost of your NSString from in a higher place:

> po $rdx = 0x0000618000644080 > proceed > Washed        

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

Resume the debugger past using the continue command:

(lldb) continue        

Endeavour exploring the SpringBoard Simulator app and meet what content has changed. Swipe upwards from the bottom to bring up the Command Heart, and observe the changes:

Try exploring other areas where modal presentations can occur, every bit this will probable consequence in a new UIViewController (and all of its subviews) existence lazily loaded, causing the breakpoint action to be striking.

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

This is also useful from a debugging standpoint, equally you lot can quickly visually verify where the -[UILabel setText:] is executed within the SpringBoard application and run breakpoint weather to find the exact line of code that sets a item UILabel'southward text.

To proceed this idea, any UILabel instances whose text did not change too tells yous something. For example, the UIButtons whose text didn't change to Yay! Debugging! speaks for itself. Peradventure the UILabel's setText: was called at an earlier fourth dimension? Or maybe the developers of the SpringBoard application chose to use setAttributedText: instead? Or maybe they're using a private method that is non publicly bachelor to third-party developers?

Every bit you tin see, using and manipulating registers can give you lot a lot of insight into how an awarding functions. :]

Where to Go From Here?

Whew! That was a long 1, wasn't it? Sit dorsum and take a suspension with your favorite form of liquid; y'all've earned information technology.

You tin can download the completed project from this tutorial here.

So what did you learn?

  • Architectures ascertain a calling convention which dictates where parameters to a role and its render 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 then on.
  • In Swift, RDI is the first argument, RSI is the 2nd parameter, and so 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.
  • Make sure you use the Objective-C context when printing registers with $.

There's a lot you can do with registers. Try exploring apps you lot don't have the source code for; it'due south a lot of fun and will build a good foundation for tackling tough debugging problems.

Effort attaching to an application on the iOS Simulator and map out the UIViewControllersouthward every bit they appear using assembly, a smart breakpoint, and a breakpoint command.

If you enjoyed what you learned in the tutorial, why not check out the complete Avant-garde Apple Debugging & Reverse Engineering book, bachelor on our shop?

Here's a taste of what's in the book:

  • Getting Started: Learn your style effectually LLDB and its extensive list of subcommands and options.
  • Python Power: Use LLDB's Python module to create powerful, custom debugging commands to introspect and augment existing programs.
  • Understanding Associates: Truly understand how code works at an assembler-level and how yous tin can explore code in memory.
  • Ptrace and Friends: Acquire how to leverage ptrace, dlopen and dlsym to hook into C and Swift functions to explore lawmaking that you don't have the source for.
  • Script Bridging: Extend the debugger to brand it do almost anything you want, and learn how to pass in options or arguments to your debugging scripts.
  • DTrace: Dig deep and hook into a function with a DTrace probe to query a massive corporeality of procedure information.
  • …and more!

By the end of this book, you'll have the tools and knowledge to answer even the most obscure question virtually your code — or someone else'due south.

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

If you accept any questions or comments on this tutorial, feel free to join the discussion beneath!

How To Add Registers In Assembly,

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

Posted by: maestaswhowere1953.blogspot.com

0 Response to "How To Add Registers In Assembly"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel