Want to actually understand how signed integer multiplication works at the CPU level? In this straight-to-the-point x86-64 assembly tutorial we dive into the IMUL instruction – the proper way to multiply signed integers in YASM/NASM on Linux.
We cover:
- The difference between unsigned (MUL) and signed (IMUL) multiplication
- Two-operand vs three-operand IMUL forms
- Multiplying immediate values vs global variables
- Loading values into registers (mov) and performing fast multiplication
- Basic addition with ADD and INC
- Full working example that prints results so you can see it in action
- Why you should respect the ABI and save callee-saved registers (R12-R15)
Everything is built with YASM on Ubuntu, linked with a tiny C driver, and run instantly. No fluff, just real assembly code you can copy and run right now.
Code on screen, calculator verification, and clear explanation of every line. Perfect if you’re learning low-level programming, reverse engineering, or just want to know what really happens when you write a = b * c; in C.
Introduction to Integer Arithmetic 00:00:00
Recommended Book and Resources 00:00:39
Instruction Set Overview 00:01:17
Addition Instruction (ADD) 00:01:43
Unsigned vs Signed Multiplication 00:02:20
Signed Multiplication with IMUL 00:03:05
IMUL Three-Operand Form 00:03:40
IMUL Two-Operand Form 00:04:12
Squaring with IMUL 00:04:50
Setting Up the Sample Program 00:05:08
Data Section and Strings 00:06:13
Text Section and External Functions 00:06:58
Math Function Entry Point 00:08:01
Multiply Test Function Setup 00:08:42
Multiplying Immediate Values 00:09:48
Printing the Immediate Result 00:10:21
Running and Verifying Immediates 00:12:53
Multiplying Global Variables 00:13:49
Loading Globals into Registers 00:14:07
IMUL with Globals Demo 00:14:37
Addition with INC and ADD 00:15:36
Final Results and Verification 00:17:09
Wrap-Up and Closing 00:17:22
Outro and Subscribe Request 00:17:44
Thanks for watching!
Find us on other social media here:
- https://www.NeuralLantern.com/social
Please help support us!
- Subscribing + Sharing on Social Media
- Leaving a comment or suggestion
- Subscribing to our Blog
- Watching the main “pinned” video of this channel for offers and extras
okay
hey everybody in this video i’d like to talk to you a little bit about
integer arithmetic in yasm assembly on an x86-64 system
so what am i talking about well integer arithmetic i want to take integers and i want to add them
together multiply them together whatever this video is mostly going to focus on signed integer
but I’m going to briefly skim through unsigned integer multiplication and also
addition and anyway so for starters let me go up to this the top of this book
here that I’ve got I’m going to show you pages from a book that I really really
love I mentioned it in a lot of my other videos it’s called x86 64 assembly
language programming with Ubuntu and it is written by a brilliant doctor
professor who is just interested in everyone learning this is an open source
you can get yourself a copy for free just look that title and name up you can find his website
you can grab a copy and you too can become an assembly expert just by reading this book
honestly this book has everything that you really need to to really level yourself off
level yourself up well beyond i think the master’s level of college probably
not as much as the person who wrote the book but you never know anyway let me uh
I want to go down to section 7 here and it’s called instruction set overview.
So here you can have like an overview of like all different types of instructions, but I’m
going to focus on the integer arithmetic instructions.
So I’m going to go to 7.5.
Notice how the first section in here is addition.
I’m not going to give you an addition example because it’s just too easy.
You pretty much use just use the add instruction and then you have a source and destination
comma source in x86 yasm assembly it’s pretty much the destination is the first operand so uh
that’s kind of implied usually when you have just like a two operand instruction now we could add
using three operands and the the first one would be the destination and then the other two would
be the sources but i’m going to scroll down past that to the integer multiplication section 7.5.3
unsigned multiplication is a little tricky and
You kind of have to decide what data size you’re going to go with and then you use the instruction
uh, and then you end up with some some uh, some answers that are spread across multiple registers
I’m going to eventually make other videos where I can talk to you about how to manipulate multiple registers or at least know that they’re there like
not 64-bit registers so if we were clever we could just sort of manipulate those so that
the whole answer showed up on one single 64-bit register if we wanted to but just know you can
multiply unsigned integers it’s a little bit more complicated than signed integers so in this video
i’m just going to talk about signed integers let’s see so signed integer multiplication
so in order that’s a section 7.5.3.2 if you want to multiply two integers and they’re signed
and they’re signed meaning they have a plus or a minus sign meaning they’re designated as either
positive or negative rather than not designated at all which would usually just mean positive
you can use imall as an instruction and well you can just provide you know one operand two operands
or three operands let’s do the three operand version first because that’s probably the easiest
So we would take a number that’s sitting in a register and then we would multiply it by some immediate.
Notice how IMM is sitting here.
The result of multiplying a register by some number would just go into the destination operand.
So that means you’d put a register here.
You’d put a register here.
You’d put an immediate here in one instruction.
Then you’d have some sort of an answer on what these two numbers were multiplied against each other.
then you’re allowed to specify a register for the destination and a register for the source.
But notice how the destination gets overwritten here.
So, you know, it’s going to multiply this number by this number
and then just store the result in the first register.
So you will kind of overwrite something.
It’s maybe more convenient for you to use the three operand version
if you only want to multiply by an immediate.
But, you know, anyway, and then for the, let’s see, let’s see, I think you can square a number
just by specifying its source here.
It’ll multiply a number by itself.
And then let me just go down a little bit.
I’m starting to get lost in this book.
Let me go down a little bit.
Well, I guess that’s all we really had to say.
Okay, so let me show you a sample program that I’ve prepared.
that I’ve prepared so that we can multiply. Okay, sample program. I think I need to rehearse myself
a little bit more before I record videos. Anyway, I’ve got this empty source code file here. Keep in
mind that I don’t need that. Keep in mind that I have a sample program here already. I’m not going
to really focus on the contents of it because this is not what did I do wrong here? Main and math.
main empty no no where’s my make file oh I forgot to open it this is not a video
about make files or hybrid programs or anything like that that’s covered in my
other videos so I’m just gonna say hey I’ve got a make file that compiles my
assembly source code and then I’ve got a driver C source code file which its
entire job is just to have the main entry point because I’m linking against
the GCC libraries and then its job is just a call on a math function which
So now my assembly module is blank.
What should we do?
First I’m going to copy paste from my solution here, just a bunch of strings.
So I’ve got a data section that I’m going to get set up.
This is not a video about the basics of assembly programming.
See my other videos, but for now I’m just going to say, well, I’ve got a bunch of strings.
I’m going to say the result of multiplying immediates is this, the result of multiplying
globals is that.
multiplications and then see the results. Okay, so then a couple more variables
before we’re finished is I’m gonna now say that we have a system call for
system right which is not what this video is about. See my other videos for
system calls. Same thing for file descriptors it’s there I’m not gonna
explain it too much I’m just gonna print a standard output and then from this
program we’re gonna I’m gonna return just an integer for whatever reason I’m
for whatever reason. I’m just saving it as a variable. And then we want to multiply some
integers. So I’m storing two integers in the global section, you know, still inside of the
dot data section. So that’s, these are going to be global variables. They’re going to be both
be quad words. So I can load up into a quad registers or quad word registers. And now I’m
ready to start my text section. So the first thing that I’m going to do is just, you know,
that’s where all of our instructions go and then I’m going to name two external
symbols don’t worry about these symbols they are not the point of this video but
you know I have a little library that I wrote that helps me print and and take
input from the user I’m gonna print an integer I’m gonna take an input from the
from the user so don’t worry about that that’s not the point of this video
really I just want to make it so that when I demo I can just easily type in an
and then just print it to the user.
So let’s look at our main entry point here.
Remember the driver calls on a function called math.
So I’m just gonna make an entry point called math,
mark it as global so the driver can call on it.
And then I’m gonna, whoops, why did I put load here?
Do, I’m gonna put, I’m gonna say do it right there.
Let’s do it.
I’m just gonna call on a function I wrote
called multiply test, kind of pointless
if you think about the fact that there’s like no code
in the main function here.
like no code in the main function here but that’s the way i like to do it when we’re done we’re just
going to return our return value that’s already been defined and so now i’m ready to start setting
up our multiply test maybe i’ll just copy paste the header here and i’ll say this is going to be
a label called multiply test because i’m going to call on it and try to use it like a function
i’m going to put a return instruction at the very end so now it really is a function
I’m going to use these registers.
So I’m going to use R12, R13, R14, and R15 to hold temporary immediates and globals
just for multiplication.
So I’m basically going to be using the registers to hold my data.
And because I’m going to use all of those registers, remember you have to respect the
ABI.
So that means we have to have a push pop pair on all of those registers because they’re
designated as callee saved.
saved if anyone calls on your functions and you’re not respecting the abi then you’re probably about
to crash the program in some way or even if you are the only person who writes any code that your
code calls on or gets called from you’re probably still going to regret not respecting the abi
eventually when you forget what’s going on anyway so let’s multiply some immediates first thing i’m
and move it into R12 because that’s where we’re going to hold some temporary
immediates and then the number 256 put that into R13 and then I’m going to use
the I’m all instruction to just multiply those two values together because this
is the two operand version of that instruction the result will also be
stored in R12 so that means 233 will be erased from R12 and the answer that will
the results for the immediate because I like my programs to be pretty. I’m not just going to print
the numbers and then hope I can remember which number comes first. That’s usually a huge mistake
if you’re trying to debug something even a little bit complicated. So I’m going to print my string,
which I’m calling the immediate prefix. And if you look back up at the top right here,
it’s just going to say the result of multiplying immediates is, and then it’s going to put three
asterisks. And then I’m going to print the actual result. And then the suffix is just going to be
And then the suffix is just going to be three more asterisks.
So we should basically see the results surrounded by asterisks.
So I’m doing that.
And then I’m going to use my library
to call a special printing function
so that I can just print to the result.
So R12 is where the result of the multiplication is.
I’m going to give that as the first argument,
which is the RDI register, if we’re talking about integers.
And then I’m just going to call my function
that’ll print for me.
for me and then I’m going to print the suffix so the suffix is just that other
string we talked about just it trails with asterisks I’m then going to call
on a custom function called crlf all that’s going to do is just print a new
line I don’t know why I do that I could easily put that into the string but it’s
more fun to call functions although to be fair every time you call a function
you are jumping to an instruction elsewhere and so the CPU does pay a
trying to write programs for high performance you might not want to do that anyway so this is pretty
fast because i’m really just using an immediate and then i’m loading it into a register i’m not
actually touching global memory so this should be a lightning fast multiplication operation
let’s see if this actually works if i didn’t screw this up whoops what did i what did i do there oh no
i have too many videos now
gosh okay clear and make run oh what have I done undefined symbols CRLF did I
forget oh I forgot to copy paste my CRLF function yeah so again don’t worry
about CRLF all I’m doing is just printing a new line carriage return it’s
just you know this is from another example where I was trying to prove to
somebody you need to preserve registers and respect the ABI so don’t even worry
you know what I’m going to leave it as is because if I take that out then I have to take the time
to remove the push pop pair because there’s no point at that I’m doing that if I’m not
messing with those registers forget about that it’s not part of this video
anyway I’m going to run the program again and you can see that the result of multiplying
immediates is and so this whole string right here was my prefix so again not really the point of
the point of this video and then this is the result of multiplying those two different numbers
and then the suffix with the stars after so let me just prove this to you where’s the dang calculator
oh man i need to work on my icons like i just did something screwy and i have like no good icons
anymore on this virtual machine so we were going to multiply 233 by whoops by what was it 256.
five nine six four eight and you can see that’s on the screen five nine six four eight so we have
successfully multiplied signed integers and since they’re signed we could multiply negative numbers
if we wanted to i’m not going to here but you can now the next thing let’s try is let’s multiply
stuff sitting in global memory okay so i’m just going to copy this um where the heck is it
at the top we made two global integers we said integer a is equal to 233 and then 256
those were the same numbers that we just multiplied so we should probably get the same result
if we’re lucky so i’m saying i’m going to move both of these into registers so i’m going to move
a into r14 and i’m going to move b into r15 just to prove to you that we can and then
instruction we did before the result is going to go into r14 so let’s see i’m gonna print the
prefix real fast here same kind of concept that we talked about before there’s just going to be
a prefix before the result and then i’m actually going to print the result with this line right
here or these lines i’m just going to print r14 which is holding the result at this point
and hey we can trust that R14 wasn’t killed by the system call because the
system call respects the ABI and then I’m gonna print my suffix right here and
then a CRLF and that’s basically the idea let’s just double check here that
we get the same result twice make run notice how it prints the same result
twice once with globals once with immediates so if you were wondering
before this video how to multiply immediates or how to multiply globals
well there you go just put them into registers first and then call I’m all
pretty fast let’s just do one other thing for fun I’m going to let’s see add
one number to our 14 so to the result of the multiplication and then I’m going to
add five to it just to prove to you that we can increase an integer by one and we
we print it before we do the prefix extra stuff just for fun so here I’m gonna increase r14 and
I’m gonna say that it is a q word I guess that’s implied already because r14 is considered a 64-bit
register but if we wanted to increase I don’t know just for the sake of argument if we wanted
to like increase this right here let me just show you real fast how we do it we would say increase
would say increase q word and then name the integer in global memory so in global memory
the system doesn’t really know by default if it’s a one byte integer a two byte integer or four or
eight so you just have to specify the data size so it knows which integers to look at when it’s
considering what the original value is and how to overflow and when to overflow but you know just
for fun I’m putting that in here so it’s going to increase the result by one and then it’s going to
and it’s going to do that using the addition instruction.
So we’re going to add R14 with 5.
We can put an immediate there,
and the result is going to be stored in R14.
So basically R14 is equal to R14 plus 5.
And so overall, when we add those two things in there,
the second result should now be about 6 higher than the first result.
So if you kind of look at this right here,
we have 648, and then we have 644,
which is 6 numbers higher than the original result.
than the original result. So these are the basics of integer arithmetic with
signed multiplication and addition. I think that’s all I really wanted to show
you. Yeah, okay. So I hope you learned a little bit of stuff from this video. I
hope you had a little bit of fun. Come back, I’ll see you in the next video and
happy coding! Hey everybody! Thanks for watching this video again from the
appreciate it. I do hope you did learn something and have some fun. If you could do me a please,
a small little favor, could you please subscribe and follow this channel or these videos or
whatever it is you do on the current social media website that you’re looking at right now.
It would really mean the world to me and it’ll help make more videos and grow this community.
So we’ll be able to do more videos, longer videos, better videos, or just I’ll be able to keep making
kindness and uh and subscribe you know sometimes i’m sleeping in the middle of the night and i just
wake up because i know somebody subscribed or followed it just wakes me up and i get filled
with joy that’s exactly what happens every single time so you could do it as a nice favor to me or
you could you could troll me if you want to just wake me up in the middle of the night just subscribe
and then i’ll i’ll just wake up i promise that’s what will happen also uh if you look at the middle
of the screen right now you should see a qr code which you can scan in order to go to the website
which I think is also named somewhere at the bottom of this video.
And it’ll take you to my main website where you can just kind of like see
all the videos I published and the services and tutorials and things that I offer
and all that good stuff.
And if you have a suggestion for clarifications or errata or just future videos that you want to see,
please leave a comment.
Or if you just want to say, hey, what’s up? What’s going on?
You know, just send me a comment, whatever.
I also wake up for those in the middle of the night.
middle of the night I get I wake up in a cold sweat and I’m like it would really it really
mean the world to me I would really appreciate it so again thank you so much for watching this video
and um enjoy the cool music as as I fade into the darkness which is coming for us all
Thank you.

