Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the operation address incremented by two?

I am looking at a Javascript emulator of a NES to try and understand how it works.

On this line:

    addr = this.load(opaddr+2);

The opcode is incremented by two. However, the documentation (see appendix E) I'm reading says:

Zero page addressing uses a single operand which serves as a pointer to an address in zero page ($0000-$00FF) where the data to be operated on can be found. By using zero page addressing, only one byte is needed for the operand, so the instruction is shorter and, therefore, faster to execute than with addressing modes which take two operands. An example of a zero page instruction is AND $12.

So if the operand's argument is only one byte, shouldn't it appear directly after it, and be + 1 instead of + 2? Why +2?

This is how I think it works, which may be incorrect. Suppose our memory looks like:

-------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | <- index
-------------------------
| a | b | c | d | e | f | <- memory
-------------------------
  ^  
   \ 
     PC

and our PC is 0, pointing to a. For this cycle, we say that the opcode:

var pc= 0; //for example's sake
var opcode= memory[pc]; //a

So shouldn't the first operand be the next slot, i.e. b?

var first_operand = memory[pc + 1]; //b
like image 514
Gavin Jones Avatar asked Oct 27 '12 03:10

Gavin Jones


1 Answers

Your analysis appears to be correct at first glance but since the emulator works there must be something else going on.

The relevant code is as follows :

    var opinf = this.opdata[this.nes.mmap.load(this.REG_PC+1)];
    var cycleCount = (opinf>>24);
    var cycleAdd = 0;

    // Find address mode:
    var addrMode = (opinf >> 8) & 0xFF;

    // Increment PC by number of op bytes:
    var opaddr = this.REG_PC;
    this.REG_PC += ((opinf >> 16) & 0xFF);

    var addr = 0;
    switch(addrMode){
        case 0:{
            // Zero Page mode. Use the address given after the opcode, 
            // but without high byte.
            addr = this.load(opaddr+2);
            break;

Note how on the first line shown, the memory access to get the instruction information is at address REG_PC+1. So the PC actually points to the byte preceding the opcode being executed and so the operands start at that address + 2. The opcode itself is encoded as the lower 8 bytes of opinf and used in the execute switch a page or so below the code segment shown.

like image 71
HBP Avatar answered Oct 08 '22 08:10

HBP