-2

I have been really into hardware recently and been researching about how CPU's work. To do this, I've been making an assembler, disassembler, and vCPU for a made-up CPU architecture.

I have learned a lot, but there's something I still don't understand. How does an assembler / CPU handle variables?

From what I understand, local variables are allocated and stored on the stack. But when the CPU reaches an instruction that needs the value of a local variable, how does it know where it is on the stack? The assembler can't put in an address at compile time, right?

I don't really understand global variables except that you have them in the .data section (x86 asm). When the CPU reaches a instruction that needs the value of a global variable, how does it know where it is in memory? Wouldn't it be in different places every time the program is ran? So then the assembler can't give it an address, right?

I've been looking everywhere for the answers, yet haven't found them.

4
  • I'm confused on why this got downvoted, isn't this the place that hardware and the such can be talked about? meta.stackexchange.com/a/57999 Jul 9, 2022 at 4:09
  • You've "been making an assembler, disassembler, and vCPU for a made-up CPU architecture" but you haven't grasped the concept of pointers?
    – Zac67
    Jul 9, 2022 at 12:21
  • @Zac67 I do understand pointers, I use them all the time and they are very useful. I should of probably listed things I do know, as that would of probably helped out a lot. I'm sorry. Jul 9, 2022 at 17:24
  • And I have stated that "I have been really into hardware recently" so this is all very new to me. The lowest I have gone previously is C, which I knew isn't the lowest as it's only a "Mid-level language". Jul 9, 2022 at 17:32

1 Answer 1

2

At the CPU level they are not variables, they are simply addresses, registers and other locations. The stack is not necessarily the place where they are stored.

While you might have higher level code that says

Add `variable1` to `variable2`

At the machine code level this would be broken down to simpler instructions (using pseudo-code, not true x86 assembly)

Read memory address of `variable1` into register A
Read memory address of `variable2` into register B
Add resister A to register B
Store result in memory address of `variable3`

Variable names are only there for you to use as a human being, the CPU does not care about them and they will be replaced with relevant program memory addresses by the assembler.

As far as I remember (it has been 20 years) the stack is not meant for random access. You can push values onto the stack or pop off the last item but saying give me item 9 on the stack is not how it works. At best it would be

Pop item from stack into register A
Pop (next) item from stack into register B
Add register A to register B
...

If you need item 9 on the stack then you would have to pop the first 8 items off it first and presumably do whatever work was necessary with them first. It is a queue, not random storage. Specifically it is a LIFO (Last In First Out) queue.

So as an example if you are going to call a function you may well push two items onto the stack to pass as "variables". The first thing the receiving code would do is pop those off the stack:

Main code:
    Push variable2 onto stack
    Push variable1 onto stack
    Jump to code at address (AddNumbers)

AddNumbers:
    Pop variable 1 from stack to register A
    Pop variable 2 from stack to register B
    Add register A to register B

(Note the reverse order of pushing items onto the stack)

How variables are kept as local and global is not really something for the CPU to care about. It is an issue of semantics and descriptive language used by the assembler program to decide where in memory it is going to arrange named variables before replacing their name with an address in the machine code, as well as on giving the ability to re-use simple names in a local scope.

Assembler code might be "close to the bare metal" but there are still obfuscation such as variable names, local and global scopes, and other things used to make them simpler for humans to handle. They still need a program (the assembler) to rewrite them in actual machine code before the CPU can use them.

7
  • Since I Don trust the author knows better, the assembly code provided is a pseudo language, it would actually be x86 instructions.
    – Ramhound
    Jul 9, 2022 at 16:42
  • @Ramhound I have added a comment clarifying that the sections are pseudo code. My main experiences of assembler is with 68000 and Z80 assembler and while I can remember the intent of the instructions I dont remember the actual instructions themselves.
    – Mokubai
    Jul 9, 2022 at 16:56
  • I missed that statement…
    – Ramhound
    Jul 9, 2022 at 16:58
  • @Ramhound sorry, I meant that I had just added it. I had hoped what I was written was obviously not x86 code and was just an English language equivalent.
    – Mokubai
    Jul 9, 2022 at 17:01
  • I do understand that it's pseudo language, and I don't really understand what I said wrong in the original post. I have had problems in the past where people take things I wrote in the wrong way. But anyways this does help, and it makes a lot more sense that globals are in program memory. This was originally supposed to be for locals, which probably would have helped. I got the idea that locals were in the stack from a YouTube video. Specifically, youtu.be/faMLkpC8TmA. Jul 9, 2022 at 17:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .