68000 Assembly/Addressing Modes
Addressing Modes
editn is a number between 0 and 7 denoting which register to use.
Immediate addressing with data registers
editAssembler syntax
- Dn
Directly operate on the contents of a data register. Example:
MOVE.L D1,D0
Copies the contents of D1 to D0. When the instruction is executed, both registers will contain the same information. When moving a byte or a word, the upper part of the register will remain unchanged.
;lets assume ;D0=FFFFFFFF D1=01234567 MOVE.B D1,D0 ;copies a Byte from source ;D0=FFFFFF67 D1=01234567 .... ;lets assume ;D0=FFFFFFFF D1=01234567 MOVE.W D1,D0 ;copies a Word from source ;D0=FFFF4567 D1=01234567
Immediate addressing with address registers
editAssembler syntax:
- An
Directly operate on the contents of an address register.Example:
MOVE.L A1,D0
Copies whole A1 to D0. After the instruction, both registers contain the same information. When transferring with ADDRESS registers you must use word or longword. When a word is transferred to an address register, bit 15 (the sign bit) will be copied through the whole upper word (bit 16-31). If it wasn't so, a negative number would become positive.
;lets assume ;D0=FFFFFFFF A1=01234567 MOVE.W A1,D0 ;copies a Word from source ;D0=FFFF4567 A1=01234567 .... ;lets assume ;D0=01234567 A1=FFFFFFFF MOVE.W D0,A1 ;copies a Word from source ;D0=01234567 A1=00004567 ; sign to A1, changed .... ;lets assume ;D0=0000FFFF A1=00000000 MOVE.W D0,A1 ;copies a Word from source ;D0=0000FFFF A1=FFFFFFFF ; sign to A1, changed
Indirect addressing
editAssembler syntax:
- (An)
Operate on the memory location pointed to by An. For example:
lea $1234,A1 move.w D0,(A1)
will move the first 16 bits of D0 into the word starting at $1234. Another example:
MOVE.L (A0),D0
Copies the long word starting at address location stored in A0 (you say A0 points to the long word). If you refer to a word or a long word, the address in the address register must be an EVEN number. Take care with this!!!
;lets assume ;D0=FFFFFFFF A1=00001000 ;mem.addr. $1000=01234567 MOVE.L (A1),D0 ;copies Long word starting at memory address stored in A1, to D0 ;D0=01234567 A1=00001000 ;mem.addr. $1000=01234567
Indirect addressing with postincrement
editAssembler syntax:
- (An)+
Same as indirect addressing, but An will be increased by the size of the operation after the instruction is executed. The only exception is byte operations on A7 - this register must point to an even address, so it will always increment by at least 2. Example:
MOVE.L (A1)+,D0
Copies to D0 the longword to which A1 points, and increases A1 with 4 (because of Long).
;lets assume ;D0=FFFFFFFF A1=00001000 ;mem.addr. $1000=01234567 MOVE.L (A1)+,D0 ;copies the Long word starting at address stored in A1, to D0 ;then increment A1 by 4 ;D0=01234567 A1=00001004 ;mem.addr. $1000=01234567
Indirect addressing with predecrement
editAssembler syntax:
- -(An)
Same as indirect addressing, but An will be decremented by the size of the operation BEFORE the instruction is executed. The only exception is byte operations on A7 - this register must point to an even address, so it will always decrement by at least 2. Note that there is no postdecrement or preincrement addressing mode. Example:
MOVE.L -(A0),D2
First decreases A0 with 4(size of operand), then copies the long word starting at address stored in A0 to D2.
;lets assume ;D0=FFFFFFFF A1=000010A8 ;mem.addr. $10A4=01234567 MOVE.L -(A1),D0 ;first decrements A1 by 4, A1=000010A4 ;then copies the Long word starting at address stored in A1, to D0 ;D0=01234567 ;mem.addr. $10A4=01234567
Indirect addressing with displacement
editAssembler syntax:
- x(An)
- (x)(An)
- (x,An)
Operate on the location pointed to by x + An, where x is a 16-bit immediate value. All listed syntaxes are equivalent, but some assemblers won't accept them all.
Indirect addressing with index
editAssembler syntax:
- x(An,Dn.W)
- x(An,Dn.W*scale)
- x(An,Dn.L)
- x(An,Dn.L*scale)
- x(An,An.W)
- x(An,An.W*scale)
- x(An,An.L)
- x(An,An.L*scale)
- (x)(An,Dn.W)
- (x)(An,Dn.W*scale)
- (x)(An,Dn.L)
- (x)(An,Dn.L*scale)
- (x)(An,An.W)
- (x)(An,An.W*scale)
- (x)(An,An.L)
- (x)(An,An.L*scale)
- (x,An,Dn.W)
- (x,An,Dn.W*scale)
- (x,An,Dn.L)
- (x,An,Dn.L*scale)
- (x,An,An.W)
- (x,An,An.W*scale)
- (x,An,An.L)
- (x,An,An.L*scale)
Same as above, but another register will also be added. Scale can be 1, 2, 4, or 8. Scale is not supported on all devices. Not all assemblers will take all listed syntaxes.
Absolute near addressing
editAssembler syntax:
- (xyz).W
- xyz.W
Operate on the location pointed to by letters like xyz, sign-extended by the assembler. You can write this either with or without the parentheses, and most assemblers can take either one. Which you choose is largely a matter of personal preference, but most people find (xyz).W easier to read.
Absolute far addressing
editAssembler syntax:
- (xyz).L
- xyz.L
Operate on the location pointed to by letters like xyz, sign-extended by the assembler. Some instructions only accept one or the other of near or far absolute addresses, thus the separation. Like absolute near, you can include the parentheses at your discretion.
Program counter indirect with displacement
editAssembler syntax:
- x(PC)
- (x)(PC)
- (x,PC)
Operate on the memory value at x + PC, where x is a 16-bit immediate value. Note that PC is the address of the extension word that x is stored in (right after the instruction's word). All syntaxes are equivalent, but some assemblers won't take them all.
Program counter indirect with index
editAssembler syntax:
- x(PC,Dn.W)
- x(PC,Dn.W*scale)
- x(PC,Dn.L)
- x(PC,Dn.L*scale)
- x(PC,An.W)
- x(PC,An.W*scale)
- x(PC,An.L)
- x(PC,An.L*scale)
- (x)(PC,Dn.W)
- (x)(PC,Dn.W*scale)
- (x)(PC,Dn.L)
- (x)(PC,Dn.L*scale)
- (x)(PC,An.W)
- (x)(PC,An.W*scale)
- (x)(PC,An.L)
- (x)(PC,An.L*scale)
- (x,PC,Dn.W)
- (x,PC,Dn.W*scale)
- (x,PC,Dn.L)
- (x,PC,Dn.L*scale)
- (x,PC,An.W)
- (x,PC,An.W*scale)
- (x,PC,An.L)
- (x,PC,An.L*scale)
Like PC with displacement, but another register is added as well. Scale can be 1, 2, 4, or 8. Scale is not supported on all devices. Some assemblers won't take certain syntaxes.
Memory indirect addressing
editAssembler syntax:
- ([bd,An],od)
- ([bd,An],An.W*scale,od)
- ([bd,An],An.L*scale,od)
- ([bd,An],Dn.W*scale,od)
- ([bd,An],Dn.L*scale,od)
- ([bd,An,An.W*scale],od)
- ([bd,An,An.L*scale],od)
- ([bd,An,Dn.W*scale],od)
- ([bd,An,Dn.L*scale],od)
- ([bd,PC],od)
- ([bd,PC],An.W*scale,od)
- ([bd,PC],An.L*scale,od)
- ([bd,PC],Dn.W*scale,od)
- ([bd,PC],Dn.L*scale,od)
- ([bd,PC,An.W*scale],od)
- ([bd,PC,An.L*scale],od)
- ([bd,PC,Dn.W*scale],od)
- ([bd,PC,Dn.L*scale],od)
These addressing modes perform two memory accesses - first a read in to a table of addresses, second the actual read or write. Not supported by all devices. In memory indirect preindexed mode, the CPU will first read bd+An+Rn*scale, then add od, and use the resulting value as the address for the final read or write. In memory indirect postindexed mode, the CPU will first read bd+An, then add Rn*scale+od, and use the resulting value as the address for the final read or write.
Immediate addressing
editAssembler syntax:
- #xyz
Operate on xyz.
Status Register addressing
editAssembler syntax:
- SR
- CCR
SR is the entire status register, including the system byte. CCR is just the flags. Other than that, I don't know how this works. SR is only available in supervisor mode.
The only instructions that are allowed to use this addressing mode are: MOVE, ANDI (AND immediate), EORI (exclusive OR immediate) and ORI (OR immediate) known as: MOVE to/from CCR, MOVE to/from SR, ANDI to CCR, ORI to CCR, EORI to CCR, ANDI to SR, ORI to SR, EORI to SR.
;Example ORI to CCR ;lets assume CCR=$00 ORI #5,CCR ;sets both the carryflag (C) and the zeroflag (Z) ;CCR = $05 -> 00000101 ;most assemblers recognize both SR and CCR ;so you don't have to specify the length of operand.