Does Program Counter hold current address or the address of the next instruction?

后端 未结 3 1175
抹茶落季
抹茶落季 2020-12-06 12:57

Being a beginner and self-learner, I am learning assembly and currently reading the chapter 3 of the book, The C Companion by Allen Hollub. I can\'t understand the descript

3条回答
  •  天涯浪人
    2020-12-06 13:22

    Real instruction set but it doesnt matter, and not interested in how this real instruction works it will serve to demonstrate the issue.

    2000: 0b 12        push r11     
    2002: 3b 40 21 00  mov #33, r11
    2006: 3b 41        pop r11      
    2008: 30 41        ret  
    

    As it has been mentioned there is a notion of time when talking about the program counter.

    A super simple processor, old 8 bit, and others can be thought of like this, newer ones are different.

    When we enter this code, however we get here, doesnt matter. The program counter is 0x2000. This tells us where to fetch the instruction we have to fetch it, decode it, and then execute it, repeat.

    These are 16 bit instructions, two bytes, the processor starts to fetch with the pc pointing at the instruction so the address of the instruction. The processor reads two bytes one at address 0x2000 (0x0b), the processor increments the program counter to 0x2001 and uses that to fetch the second half of the instruction at address 0x2001 (0x12) and increments the program counter to 0x2002. So for each fetch in this lets call it made up processor I am describing for each fetch you fetch using the program counter as the address then increment the program counter.

    before data after
    0x2000 0x0b 0x2001
    0x2001 0x12 0x2002
    

    So now we decode the instruction, the program counter is currently showing 0x2002, we see that this is a push r11, so we move on to execute.

    During execution of this instruction the program counter remains 0x2002. The register r11's value is pushed onto the stack.

    Now we begin to fetch the next instruction.

    before data after
    0x2002 0x3b 0x2003
    0x2003 0x40 0x2004
    

    As we decode this instruction (pc == 0x2004) mov #immediate,r11 the processor realizes that there is an immediate required for this instruction so it needs to fetch two more bytes

    before data after
    0x2004 0x21 0x2005
    0x2005 0x00 0x2006
    

    It has determined that it can now execute the instruction (little endian 0x0021 = 33decimal) by writing the value 0x0021 into register r11. During execution the program counter is 0x2006 for this instruction.

    next

    before data after
    0x2006 0x3b 0x2007
    0x2007 0x41 0x2008
    

    decode and execute a pop r11

    So you can start to see that the program counter does actually contain at least two values. At the start of the instruction before fetching it contains the address of the instruction, after fetching and decode just before we start to execute it contains the address of the byte after this instruction which if this is not a jump is another instruction. If this is an unconditional jump that byte could be an instruction or some data, or unused memory. But we say that it "points to the next instruction" meaning in this case before execution the address after this instruction which often has another instruction. But as we will see next the pc can be modified by the instruction. But always at the END of execution it points (for this simple made up processor which is similar to a number of simple 8 bit processors) to the next instruction to be executed.

    lastly

    before data after
    0x2008 0x30 0x2009
    0x2009 0x41 0x200A
    

    decodes a ret, now this one is special as far as the question goes because a ret is going to modify the program counter during execution per the rules of this processor. If the instruction that called address 0x2000 was say 0x1000 and it was a two byte instruction then after fetching and during decoding the program counter would be at address 0x1002, during execution the address 0x1002 would be stored somewhere per the rules of this instruction set and the program counter would take on the value 0x2000 to call this subroutine. When we get to the ret instruction and begin to execute it then we start execution of the ret with the program counter containing 0x200A but the ret puts the address of the instruction after the call, the value stored during the execution of the call, so at the end of this instruction the program counter would contain the value 0x1002 and the next fetch would be from that address.

    So in this last instruction just before execution the pc points to what would normally be the next instruction for instructions that dont branch or jump or call. 0x200A. But during execution the program counter has been changed so that the "next" instruction is the one after the call that got us here.

    some more

    c064:   0a 24           jz  $+22        ;abs 0xc07a
    c066:   4e 5e           rla.b   r14     
    

    before fetching the pc is 0xC064. after fetch and decode the pc is 0xC066. The instruction says jump if zerp to 0xc07a. So if the zero flag is not set then the pc stays at 0xC066 and that is where it starts the next instruction, but if z is set then the pc is modified to 0xc07a and that is where the next instruction to execute will be. So before 0xc064 after 0xc066 or 0xc07a depending.

    The after of one instruction is the before of the next.

    unconditional jump

    c074:   c2 4d 21 00     mov.b   r13,    &0x0021 
    c078:   ee 3f           jmp $-34        ;abs 0xc056
    

    before fetching 0xc07a, before execution 0xc07A after execution 0xc056

    for that one instruction the pc held at least three values (if fetching a byte at a time then it held 0xc078, 0xc079, 0xc07a and ended with 0xc056) during one instruction.

    yes it can and does hold more than one value, but not at the same time, one value at a time during the phases of the instruction.

提交回复
热议问题