DEV Community

Buğra Yıldız
Buğra Yıldız

Posted on

Basic Arithmetic in Assembly

Hello there!

So basically I just figured out how to do those 4 simple operations (adding, diving etc.) in assembly, because I need to be able to do maths in my own programming language. So here's the recap of all the pain I've been through thanks to intel:

This article is useful for people using intel x86_64 architecture with the GNU assembler, gas. You also have to use .intel_syntax noprefix macro so you can use the intel syntax, which this tutorial uses.

Addition

First things first, get your values into your 64 bit teeny tiny registers:

mov rax, 1
mov rbx, 2
Enter fullscreen mode Exit fullscreen mode

The rest is pretty simple:

add rax, rbx
Enter fullscreen mode Exit fullscreen mode

The result is in rax, which is 3.

Subtraction

Same as always:

mov rax, 10
mov rbx, 2
Enter fullscreen mode Exit fullscreen mode

Then again:

sub rax, rbx
Enter fullscreen mode Exit fullscreen mode

The result is in rax, which is 8.

Multiplication

So, this one instruction actually has 2 ways of using it, but for the sake of simplicity, I will show you the easiest one, which is most likely erroneous because if you are writing a production ready compiler or the production code directly you HAVE TO check if multiplying two 64 bit numbers result in a 128 bit number, because if it does your result will be incorrect. But who cares right?

mov rax, 5
mov rbx, 2
Enter fullscreen mode Exit fullscreen mode

Then a simple operation:

imul rax, rbx
Enter fullscreen mode Exit fullscreen mode

Aaaanndd, the result is in rax, which is 10.

Division 🤢

So, this one is probably the messiest within the four, but here we go ladies and gentleman. This instruction takes only a single, explicit argument and an implicit argument. But using it with a little hack is pretty easy. Firstly, unlike any other instruction up until you have seen, this one requires that the dividend MUST be in the rax register.

mov rax, 100
mov rbx, 5
Enter fullscreen mode Exit fullscreen mode

Then, before diving it you have to put this instruction for some complicated reason, which affects registers rdx and rax. I will tell more in a minute, but just divide by then:

cqo
idiv rbx
Enter fullscreen mode Exit fullscreen mode

Your result should be in rax, and the remainder of this operation is in register rdx.

The problem with dividing is that, because it affects other registers that you don't mention, often times when rax and/or rdx has values you actually have to store them somewhere. One way to get around this is using the stack:

note that you can put them in unused registers too!

# store those values on the stack
push rax
push rdx

# divide
mov rax, 100
mov rbx, 5
cqo
idiv rbx

# move the result to unused registers
mov r8, rax
mov r9, rdx

# then retrieve back those values, notice the order is reverse!
pop rdx
pop rax
Enter fullscreen mode Exit fullscreen mode

Conclusion

I don't hate intel, but that way of dividing is uhhh... Nevertheless, this is a funny thing to know and pun your coworkers because you can do maths in ASSEMBLY now and they can't cuz they have a life and shit. Can't understand humans, see you later!

Top comments (0)