Page 2 of 3
The simplest addressing mode is Immediate addressing where you write the data value into the instruction.
In Pentium assembler this is the default and:
means move the value 4 into the EAX register.
Immediate addressing may be the default but as we have already discovered it isn’t the most fundamental – Direct memory addressing is. This is written:
where loc is a symbolic address.
Now we have to take a slight detour to answer the question “what is a symbolic address?”!
The answer is that instead of referring to absolute addresses, such as location 1234, assembler lets you give a name to an address such as:
This defines loc to be a location in memory able to store a double word, i.e. a 32-bit memory location. Where is loc exactly? Well it doesn’t matter because the assembler gives it a real numeric address when it translates the program to machine code for you. So:
gets translated to move the contents of the memory location specified by loc into EAX. That is suppose when the assembler starts to translate the program the location loc turns out to be at address 1000. Then when the assembler reaches the MOV instruction is translates loc into the absolute address 1000.
Assemblers to a lot of symbol to number translation. For example the MOV instruction is translated to a numeric op code that causes the processor to actually do the move instruction. Translating a symbol such as loc into an address is just part of the same task of changing symbolic references into absolute references.
This is becoming very sophisticated but now consider the following very standard problem.
All you want to do is load the EAX register from a set of values stored in loc, then loc+1, loc+2 and so on until you have processed all of the data. If you know a high level language this will remind you of processing an array - which of course is exactly what it is.
One way of doing this is to give every memory location a label:
and then write:
and so on. Now try the same approach on 1000 memory locations! You can see it doesn’t work very well. We need a better solution.
The standard way of solving this problem is to invent register indirect addressing.
The EBX register holds the address of the memory location to be loaded into EAX
In this case a second register is used to hold the address of the memory location to be used in the instruction.
The idea is that you really want to do some arithmetic with the address and access consecutive memory locations loc, loc+1, loc+2 and so on, so what you need is to be able to do arithmetic on the address. Arithmetic is done in registers so storing the address in a register is the solution.
For example, there is another register in the Pentium called the EBX register – B not just being the next letter after A but also standing for “Base” – and this can be used for register indirect addressing. The instruction;
loads EAX with the location that EBX addresses.
There are lots of complications with exactly how this is achieved but you can see how this would solve our problem. If the EBX register is first loaded with the address of the first location, e.g. loc, then:
loads EAX with the contents of loc.
If we now increase the value in EBX by adding a constant so that it “points” to the next location then the next time we do MOV EAX,[EBX] we get the next location and so on until we have finished.
Now you know why there is one more register in addition to the EAX register. As more sophisticated addressing modes are added so more addressing registers are added. This can become very complicated.
Once you have the idea of using a register to supply the address used in an instruction, things can get complicated.
However, the general principles are that either the register contains the data or the address of the data.
The need to work with array type data access also gives rise to the next most common addressing mode. In this case the register doesn't hold the address of the data. Instead it stores the offset from a fixed address. This is called indexed addressing because the memory is assumed to hold a set of similar types of data and the register picks out which one of the set will be accessed. Again this is like writing myarray[i] where i is the index of the array element you want to access.
For this to work the register contents have to be added to an address to give the complete indexed address. For example:
loads EAX with the address obtained by adding the contents of the ESI register to the address specified by loc. That is when loc is given a numeric value by the assembler the instruction adds the value in ESI to the value of loc to give the final address.
ESI is the Source Index register and there is an EDI, or Destination Index, register as well.
You can easily see that indexing can be used to step though a set of memory locations in the same way as register indirect addressing.