How can we jump to different memory address in Smalltalk? - smalltalk

I am trying to build an assembly language interpreter in Smalltalk. Is there any command if I want to jump to a different memory location?
Example: There is an array of the memory address from 1-10.
1 LDI 10 //Load 10 to a register
2 XCH //Exchange value with different register
3 LDI 20 // Load 20 to a register
4 ADD //Add the values 10 and 20
5 JMP 1 //Jump to memory address 1
6 HLT
To jump from memory address 5 to address 1, is there any command?

If you are trying to model an assembly interpreter you need to represent several objects. At least you will need to have objects (i.e., classes) for registers, instructions and memory. In this design, a program (or routine) would be a sequence of instructions and your interpreter would have an instruction pointer ip that moves along the routine.
At every position of the ip, the interpreter would have to "execute" the current instruction, which would result in modifications to the registers and or specific memory locations.
For instance, you start the interpretation by assigning 1 to ip. Now you read the instruction with index ip, in this case:
1. LDI 10
Then you have to send the #execute message to the instruction. In this case the execution assigns the value 10 to the object representing register I. Now you increment ip and repeat until you run out of instructions.
In this "simulation" of the processor the jmp instruction would be one of the easiest ones to interpret: it would simply change the value of the instruction pointer ip to the target location.

Related

How is value of Program Counter incremented?

I am creating a Primitive Virtual Machine which is kind of inspired by LC-3 VMs but a 32-bit version. I am feeding the machine set of instructions. After executing the first instruction, how will the PC know the location of the second instruction.
Is there a particular method to store the instructions in memory in a systematic way so that PC knows the address of the next instruction
Example - All instructions are stored in a linear way as in memory[0] = instruction1, memory[1] = instruction2 etc.
Thank you for the help.
It depends on whether your Processor architecture is RISC or CISC. In the context you asked, A CISC processor has instructions whose size vary, say from 1 to 14 bytes, like for Intel processors. If it is RISC, each instruction size is fixed, say 4 byte, like for ARM processors. All the instruction of a program are stored, in sequence, in main memory. It is the processor control unit that decides how much to increment the PC. Instructions from the main memory would be read in sequence.
So say in CISC architecture, a single 8 byte read from main memory, can contain up to 8 '1 byte' instructions, e.g., repetitive 'inc ax' instruction in Intel processors. After sending the first instruction for decode, the control unit will increment PC by 1. But, at other extreme, there could be a instruction like 'add REG , [BASE+INDEX+OFFSET]' , which can take 13 bytes to store all the information (opcode + REG id + base address + index + some offset) that is there in the instruction. For such instruction, two memory read operation would be required to fetch the full instruction. After sending it for decode, the control unit will increment the PC by 13.
For RISC it is simple. Increment PC by size (2,4,...) of instructions.
Only exception is when there is branch. In that case, PC value is reset at usually the execute stage.
Instructions and data are generally grouped (segmented in some processor architecture) and stored separately. A code segment will end with some kind of return or exit instruction. If PC is set to some memory address where data is stored, the control unit of the processor will process it as instruction. After all both data and instructions are nothing but a sequence of bits! The control unit will not be able to differentiate. It is usually the role of OS or programmer (if there is no OS, like on micro-controllers) to prevent such anomaly.

how to build a 16 bits RAM with 1 data register and a U-bus? (using Logisim)

Using LOGISIM, build a working 4-nibble RAM. The RAM must have the following elements: 4 nibbles, addressing circuits, the address register, the data register, the mode register (bit), a u-bus, and a clock. Your RAM must be able to read and write nibbles.
You will run your circuit manually by setting the address, mode and data registers, then you will start the clock. The desired action will take place. For example: if you plug in an address into the address register, and a 1 in the mode register, and a nibble in the data register, and you turn on the clock, then the nibble must be copied into the RAM nibble at the desired address.
Since you have a 4-nibble RAM then you will only have addresses 00, 01, 10, and 11. Mode register set to 1 is for write and 0 is for read.
A u-bus is needed to properly handle read and write operations between the data register and the 4-nibbles of RAM.
Elements allowed:
Connectors:
- Wires
- Input connector
- Output connector (or display)
Built-in machines and gates:
- A Bit (RS, or D)
- Clock
- AND, OR, NOT, XOR, NAND, NOR

Memory addresses, pointers, variables, values - what goes on behind the scenes

This is going to be a pretty loaded question but ever since I started learning about pointers I've been very curious about what happens behind the scenes when a program is run.
As far as I know, computer memory is commonly thought of as a long strip of memory divided evenly into individual bytes. Certainly pictures such as the following evoke such a metaphor:
One thing I've been wondering, what do the memory addresses themselves represent? I'm sure it's no coincidence that memory addresses appear as 8 digit hexadecimal values (eg/ 00EB5748). Why is this?
Furthermore, when I declare a variable x, what is happening at the memory level? Is the compiler simply reserving a random address (+however many consecutive addresses it needs for the variable type) for data storage?
Now suppose x is an unsigned int that occupies 2 bytes of memory (ie values ranging from 0 to 65536). When I declare x = 12, what is happening? What is it that I'm making equal to 12? When I draw conceptual diagrams, I usually have a box for an address (say &x) pointing to a variable (x) that occupies seemingly nothing, and I'm sure that can't be a fully accurate picture of what's going on.
And what's happening at the binary level? Is the address 00EB5748 treated as 111010110101011101001000 and storing a value of 12 somewhere, or 1100?
Mostly my confusion & curiosity stems from the relationship between memory addresses and actual values being declared (eg/ 12, 'a', -355.2). As another example, suppose our address 00EB5748 is pointing to a char 's' whose value is 115 according to ASCII charts. Is the address describing a position that stores the value 115 in 1 byte, by flipping the appropriate 1s and 0s at that position in memory?
Just open any book. You will see pages. Every page has a number. Consecutive pages are numbered by consecutive numbers. Do you have any confusion with numbered pages? I think no. Then you should not have confusion with computer memory.
Books were main memory storage devices before computer era. Computer memory derived basic concept from books: book has pages -> computer memory has memory cells, book has page numbers -> computer memory has memory addresses.
One thing I've been wondering, what do the memory addresses themselves represent?
Numbers. Every memory cell has number, like every page in book.
Furthermore, when I declare a variable x, what is happening at the memory level? Is the compiler simply reserving a random address (+however many consecutive addresses it needs for the variable type) for data storage?
Memory manager marks some memory cells occupied and tells the address of first reserved cell to compiler. Compiler associates name and type of variable with this address. (This picture is from my head, it can be inaccurate).
When I declare x = 12, what is happening?
When you declared variable x, memory cells were reserved for this variable. Now you write 12 into these memory cells. Note that 12 is binary coded in some way, depending on type of variable x. If x is unsigned int which occupies 2 memory cells, then one cell will contain 0, other will contain 12. Because binary integer representation of 12 is
0000 0000 0000 1100
|_______| |_______|
cell cell
If 12 is floating-point number it will be coded in other way.
A memory address is simply the position of a given byte in memory. The zeroth byte is at 0x00000000. The tenth at 0x0000000A. The 65535th at 0x0000FFFF. And so on.
Local variables live on the stack*. When compiling a block of code, the compiler counts how many bytes are needed to hold all the local variables, and then increments the stack pointer so that all the variables can fit below it (along with some other stuff like frame pointers and return addresses and whatnot). Then it just remembers that, for example, local variable x is at an offset -2 from the stack pointer, foo is at an offset -4 and so on, and uses those addresses whenever those variables are referenced in the following code.
Since the compiler knows that x is at address (stack pointer - 2), that's the location that is set to the value 12 when you do x = 12.
Not entirely sure if I understand this question, but say you want to read the memory at address 0x00EB5748. The control unit in the CPU reads the instruction, sees that it is a load instruction, and passes the address (in binary of course) to the load/store unit, along with some other junk like how many bytes to read. Then the LSU sends that address to some memory (probably L1 cache), and after a certain time gets the value 12 back. Then this data is available to, say, put in a register, or send to the ALU to do arithmetic, or whatever.
That seems to be accurate, yes. Going back to the first question, an address simply means "byte number 0xWHATEVER in memory".
Hope this clarified things a bit at least.
*I should probably explain the stack as well. A stack is a portion of memory reserved for local variables (and some other stuff). It starts at a fixed location in memory, and stops at the memory address contained in a special register called the stack pointer. To begin with, the stack is empty, so the stack pointer just contains the start of the stack. As you put more data on the stack, the SP is incremented. This means that you can always put more data on it simply by putting it at the address in the SP, and then incrementing the SP so that once again anything past that address is free memory.

SPU Instruction Pointer

I've been searching through the entire manuals and I can't find a single mention of the Instruction Pointer. I need this for a SPU program that I'm writing. Maybe it has a different name? Can anyone tell me how I can access the address of the instruction that is to be executed? Thanks in advance for your help.
UPDATE: Apperantly it's called the Program Counter, but how can I access it from within my SPU Program?
If you just want to get the instruction pointer, you can do it in assembly:
brsl r<n>, .+4
This loads the address of the next instruction into register r<n>.
Seems like you can get the next instruction by executing a spe_context_run operation:
int spe_context_run(spe_context_ptr_t spe, unsigned int *entry, unsigned int runflags, void *argp, void *envp, spe_stop_info_t *stopinfo)
entry
Input: The entry point, that is, the initial value of the SPU
instruction pointer, at which the SPE program should start executing.
If the value of entry is SPE_DEFAULT_ENTRY, the entry point for the
SPU main program is obtained from the loaded SPE image. This is
usually the local store address of the initialization function crt0
(see Cell Broadband Engine Programming Handbook, Objects, Executables,
and SPE Loading).
Output: The SPU instruction pointer at the moment the SPU stopped
execution, that is, the local store address of the next instruction
that would be have been executed.
This parameter can be used, for example, to allow the SPE program to
"pause" and request some action from the PPE thread, for example,
performing an I/O operation. After this PPE-side action has been
completed, you can continue the SPE program calling spe_context_run
again without changing entry.

Assembly code for optimized bitshifting of a vector

i'm trying to write a routine that will logically bitshift by n positions to the right all elements of a vector in the most efficient way possible for the following vector types: BYTE->BYTE, WORD->WORD, DWORD->DWORD and WORD->BYTE (assuming that only 8 bits are present in the result). I would like to have three routines for each type depending on the type of processor (SSE2 supported, only MMX suppported, only standard instruction se supported). Therefore i need 12 functions in total.
I have already found by myself how to backup and restore the registers that i need, how to make a loop, how to copy data into regular registers or MMX registers and how to shift by 1 position logically.
Because i'm not familiar with assembly language that's about it.
Which registers should i use for each instruction set?
How will the availability of the large vector (an image) in L1 cache be optimized?
How do i find the next element of the vector (a pointer kind of thing), i know i can make a mov by address and i assume i have to increment the address by 1, 2 or 4 depending on my type of data?
Although i have all the ideas, writing the code is a bit difficult at this point.
Thank you.
Arnaud.
Edit:
Here is what i'm trying to do for MMX for a shift by 1 on a DWORD:
__asm("push mm"); // backup register
__asm("push cx"); // backup register
__asm("mov %cx, length"); // initialize loop
__asm("loopstart_shift1:"); // start label
__asm("movd %xmm0, r/m32"); // get 32 bits data
__asm("psrlq %xmm0, 1"); // right shift 32 bits data logically (stuffs 0 on the left) by 1
__asm("mov r/m32,%xmm0"); // set 32 bits data
__asm("dec %cx"); // decrement index
__asm("cmp %cx,0");
__asm("jnz loopstart_shift1");
__asm("pop cx"); // restore register
__asm("pop mm"); // restore register
__asm("emms"); // leave MMX state
I strongly suggest you pause and take a look at using intrinsics with C or C++ instead of trying to write raw asm - that way the C/C++ compiler will take care of all the register allocation, instruction scheduling and general housekeeping tasks and you can just focus on the important parts, e.g. instead of using psrlq see _m_psrlq in mmintrin.h. (Better yet, look at using 128 bit SSE intrinsics.)
Sounds like you'd benefit from either using or looking into BitMagic's source. its entirely intrinsics based too, which makes its far more portable (though from the looks of it your using GCC, so it might have to get an MSVC to GCC intrinics mapping).