Skip to main content
GameDev.net gamedev.net
🔒 Locked

ASM variables

Started by Calin Apr 15, 2020 at 7:38 PM 18 replies 12.6k views
Original Post
Calin
Calin

In the 32 bit assembler mode (protected mode) the variable size is dictated by the registers size (which in 32 bit mode is 32) i.e. like if you want to use large variables that will result in additional work (additions and other mathematical operation on the processor) and more code?

My project`s facebook page is “DreamLand Page”
NikiTo
NikiTo

On intel, no additional work is done.
Addition of 8bit, 32, 64, or even 256bit registers takes one single cycle of the processor(EDIT: operating on integers. For floating point operations, it is a little bit more complicated). With some exceptions. In the manuals of Intel you can read a long table with the costs of every single instruction in cycles.

(often instructions take 0.25 of a cycle, as the processors can execute various instructions in parallel on a SINGLE core(this is EXTRA parallelism APART of the parallelism created by the multiple cores))

The code that a programmer writes has the same length regardless the mode.
The size of the executable varies from one mode to another, but not the amount of code written by hand.
(you can use 32bit regs from 16bit mode)

EDIT: I was unsure about bigger registers in real mode. My memories were telling me you can use extensions in real mode. I googled it and it seems my memories were not lying to me -

from: https://www.quora.com/When-an-x86-CPU-is-running-in-real-mode-can-it-be-considered-to-be-basically-an-8086-CPU-or-maybe-8088

“it still has all the fancy 32bit, MMX, SSE, etc, etc instructions, that work in real mode, ”

Anthony Serrano
Anthony Serrano

It is however important to note that the 64-bit integer registers are not available in 32-bit mode, so if you want to do 64-bit integer arithmetic you have to use MMX instructions, not the standard integer math instructions.

Calin
Calin

so newer processors keep the old registers ? i.e. a processor of current days still has 8 and 16 bit registers?

My project`s facebook page is “DreamLand Page”
fleabay
fleabay

Calin said:
so newer processors keep the old registers ? i.e. a processor of current days still has 8 and 16 bit registers?

A 10 minute Part 1 YouTube video on assembly would tell you this. RTFM, seriously. At least the first 10 pages.

I thought you were writing low-level system software in assembly just a month ago?

🙂🙂🙂🙂🙂<←The tone posse, ready for action.
NikiTo
NikiTo

Calin said:

so newer processors keep the old registers ? i.e. a processor of current days still has 8 and 16 bit registers?

Yes. It is the same registers.
AL, AH, AX, EAX, RAX is all the very same register. Only the mode changes.
64 bit mode gives you 8 extra general registers and 8 extra SSE/AVX registers.

Download the manuals for the most updated and actual information - https://software.intel.com/en-us/articles/intel-sdm

Calin
Calin

Thanks NikiTo

My project`s facebook page is “DreamLand Page”
NikiTo
NikiTo

@Calin Notice - the variable's size depends of your needs. It can be less than the size of the register.

In one single register you can have various variables. This is something a compiler would not do for you.
If you need two integer counters and none of them never reaches values more than 255, you can have two of these counters in the same register at no additional cost. You can have 8 integer variables one byte each inside the same register at some small extra cost. With ASM sky is the limit.

(Assembler for AMD and Intel varies a bit. Running ASM code manually tuned for Intel could make the program crash on AMD CPUs. On AMD CPU if you write to the lower 32 bits of the 64bit register, the upper 32 bits remain unchanged. On Intel CPUs if you write to the lower half, the upper half resets to zero. This is the bad part of assembly language - the portability problem. But if compilers store an 8 bit variable inside 64 bits register, no problems! It is so much power completely gone wasted. But we sacrifice all that for productivity. I sacrifice it too. It is sad, but understandable.)

Calin
Calin

NikiTo said:
some small extra cost

What does extra cost mean? more CPU time to perform the math operations (with these variables) when compared with the normal situation when the variables are placed in a register one at a time?

My project`s facebook page is “DreamLand Page”
NikiTo
NikiTo

It takes more time to place and access the extra variable.
Math is the same.

mov ECX, variable1
mov EDX, variable2
;---------------------------------
mov EAX, ECX
bswap RAX ;use rol/ror if you want to move it to SSE/AVX regs later
or RAX, RDX

Now you have two DWORDS inside RAX.

You access the variables in reverse order. Two extra operations. But it is hella fast compared to having to move these variables to RAM. Access to non-cached RAM could cost as much as 700 cycles of the CPU!!!!!!!!

Calin
Calin

thanks for helping me unleash the dragon

My project`s facebook page is “DreamLand Page”
Calin
Calin

So basically the variables are the same to those of higher level languages, the only difference is that it`s raw variables, no cushoning

My project`s facebook page is “DreamLand Page”
NikiTo
NikiTo

It is the same. It is always a register under the hood. Compilers sometimes produce assembler code in plain text and then use an assembler to covert it to machine code. It is the same under the hood.

A variable is what you want it to be. Example is the treating of chars as numbers in order to test if the letter is a number.

You can do the same trick of putting two variables in one single variable in C++. You can explicitly tell C++ to do it using the bitwise operators. Not sure if you can get a speedup from it.

For a game i see no reason to use ASM over C# or JavaScript.

Maybe you are working on something different but you keep it in secret. You tell us that you are making a game, but actually you make something different. Something secret.

Calin
Calin

NikiTo said:
there is always a register under the hood

got it.
maybe someone is asking himself where Im headed with this, I dont want to write an OS, but the possibility of making use of interrupts sounds intriguing.

what I dont have a very good grasp of is the how the execution of commands succession works, I understand the code pockets concept (i.e code enclosed in brackets in C), what I dont understand is how when you have for example a succession of 3 instructions/commands can you, out of thin air ,insert a new command and detour the execution. I understand that there are pointers to data (variables) and also pointers to commands/functions, but how can you break and resume execution of a command chain at run time

My project`s facebook page is “DreamLand Page”
NikiTo
NikiTo

Calin said:
maybe someone is asking himself where I`m headed with this,

I do wonder what are you doing for real.

Calin said:
but the possibility of making use of interrupts sounds intriguing.

Do you really need interrupts?

Initially i thought you want to make an OS that lives completely inside the GPU. All the things you asked, made me think that.

Calin
Calin

edited my reply above

My project`s facebook page is “DreamLand Page”
NikiTo
NikiTo

If you have a 4 cores CPU, one of these cores will be core0.
It controls the rest when booting the computer.
For all the cores and all the code you have only one interruption handling code at one single place only once. There can be variations, but still it is more or less, the same.

I say all of this because there is always a central boss.

That boss can interrupt everybody else. In order the code to not notice the STOP, everything is saved to RAM. (Actually only what is being to be used by the boss code is saved)

code:

step = 50;
bullet.x += step*unitVector.x;
Bullet.y += step*unitVector.y;

the compilers will produce this under the hood(or vectorized version, but this example is for simplicity):

step = 50;
temp = step*unitVector.x;
bullet.x += temp;
temp = step*unitVector.y;
bullet.y += temp;

now consider this:

step = 50;
temp = step*unitVector.x;
bullet.x += temp;
<<<<<< interrupt comes from the boss(could be the OS or the hardware)
temp = step*unitVector.y;
bullet.y += temp;

This is what happens:

step = 50;
temp = step*unitVector.x;
bullet.x += temp;
<<<<<< interrupt comes from the boss(could be the OS or the hardware)

save “step” to RAM.
save "unitVector.x" to RAM.
save "bullet.x" to RAM.

execute the code of the interrupt, changing the frequency of the CPU for example.
CPUFrequency = CPU.getFrequency();
If (CPUFrequency > 5mhz) {
CPUFrequency -= 5mhz;
CPU.setFrequency(CPUFrequency);
}

when the CPU is ordered to cool down restore it all

take “step” from RAM
take “unitVector.x" from RAM
take “bullet.x” from RAM

Now you can keep with the old code as if nothing happened at all

temp = step*unitVector.y;
bullet.y += temp;


This way you can even have interrupts interrupting interrupts interrupting interrupts. It is simple but effective.

The hardware has its own life and ideas. It has its own CPU to say it in a way. It can interrupt your CPU any time.

Only what is inside the CPU will be saved to RAM and then restored. The rest is already laying in RAM, no need to restore. It is more complicated than my example, but to give you an idea.

Resuming it - the OS will save a copy to RAM of everything it will override. Then, when finished, the OS will restore all that taking it from RAM back to the CPU. Your program will not even notice it. Except when the time is important. Your program will notice that time gone forward.

And there is a boss, somebody, a piece of silicon somewhere that has its own life independently of your code and can interrupt your CPU.

More technically -
https://wiki.osdev.org/Interrupts#From_the_CPU.27s_perspective

You don't need to worry about interrupts. The OS will do it all for you.

Calin said:
(i.e code enclosed in brackets in C)

In ASM it is a little bit different than that. You don't use brackets. It is more like a flow/stream of instructions.

And i feel bad for talking about OS here in this forum, because this site is about games, not ASM, not OS either.

Calin
Calin

Thanks NikiTo
with multi-core processors interrupts is easier to comprehend i.e a chief core can step in at any time. But how does that work with single core? In older OS pressing ctrl alt del would bring no matter what the blue menu the very next second( Unlike modern computers where ctrl alt del menu pops up depending on the mood of the computer at that time)

How much code/commands get saved where the interrupt takes place ?

What I want to do is so crazy I dont even dare speak about it, for now I need to get a good grasp of assembler, I promise I will either put it to work or speak about what my plan was ( if I fail to achieve). It has to do with data mining` but with focus not on gathering but rather interpretation

My project`s facebook page is “DreamLand Page”
NikiTo
NikiTo

Calin said:
But how does that work with single core?

Some controller somewhere on the motherboard will have its own live and will tell the CPU to stop. I use very broad terms as "something" or "boss", because things vary from one system to another.
The CPU obeys other bosses in the system.

Calin said:
How much code/commands get saved where the interrupt takes place ?

Only the ones that the CPU will override. Not much for Interrupts coming from the motherboard. Hardware interrupts are super fast. Don't worry about them.
I am not sure about savings between different programs. I guess everything possible is saved to RAM and restored. EVERYTHING!!!! Super slow, i guess. I can not tell how windows works. I never even tried to peek into how windows does its stuff. Ask some hacker who uses ASM. They know where every single bit goes on a Windows OS. I know nothing about it. I only can guess that for security reasons, everything must be zeroed between processes.

Calin said:
I promise I will either put it to work or speak about what my plan was ( if I fail to achieve).

I do the same. I keep it all in secret. But when i see i failed and will not work on it any longer, i share it with everybody.


I worked with ASM on the baremetal.
Sometimes i am not able to answer to your questions, because i just don't know the answer. It is faster for me to create my own OS kernel than try to study or reverse engineer the kernel of Windows. And Windows changes too fast. So every time i have to study a new kernel. No point in doing it. I am not a hacker.


Right now i am being bottlenecked on the GPU side. Because not always it is possible to parallelize the IFs. So far IFs were not a problem for me. Lots of IFs, but i parallelized them until now. But my algo starts to become too GPU unfriendly. Some day I will start coding for the AVX on the CPU side. Then i will be able to answer to most of your questions. But this could happen few months from now. Not soon at all.

(Notice, i will try to use C++ first to operate the AVX. If it fails, only then i will program completely in ASM. So IF i start using pure ASM and it will be not soon, i will able to answer to all of your questions.
I am sincerely telling you that you very very rarely need to use ASM. I will explain it to you this way - The troops of your enemy are attacking the borders of your country. The troops are only 1000 in number. Definitively Tzar Bomb is the most powerful weapon of all. Tzar Bomb is ASM. But do you really need Tzar Bomb for 1000 enemy troops? A single raid of Grad Missile System will suffice. This is what i mean - you PRACTICALLY rarely need to use ASM)

Calin
Calin

Some controller

So basically Jurassic of multi-core

My project`s facebook page is “DreamLand Page”

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.