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
The rest is pretty simple:
add rax, rbx
The result is in rax
, which is 3
.
Subtraction
Same as always:
mov rax, 10
mov rbx, 2
Then again:
sub rax, rbx
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
Then a simple operation:
imul rax, rbx
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
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
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
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)