Search code examples
assembly8051edsim51

JMP label works, but JMP n adds 2 to PC?


I tried this tutorial example to create a ramp on DAC output using EdSim51 emulator:

 CLR P0.7   ; enable the DAC WR line
loop: 
 MOV P1, A  ; move data in the accumulator to the ADC inputs (on P1)
 ADD A, #8  ; increase accumulator by 8
 JMP loop   ; jump back to loop

and it works fine. However, the 03H-30H of the ROM is reserved for interrupts. With respect to that, I coded

JMP 30h ; starts at address 0, 2B instruction
; reserved 03H-30H
ORG 30h

 ; same code as above
 CLR P0.7
loop:
 MOV P1, A
 ADD A, #8
 JMP loop

but this doesn't work: the DAC WR line is not enabled.

Following Ross Ridge's comment, I played a bit:

Using labels works as expected:

JMP main

ORG 30h
main:
CLR P0.7
...

However, it seems, that if direct address is provided, the CLR P0.7 is skipped which seems to be the source of the problem. This code also works:

JMP 2Eh ; as tested, the next instruction will be at 30h
; ...
ORG 30h
CLR P0.7
...

This code also works

JMP 30h
; ...
ORG 30h
NOP
NOP ; 1 NOP doesn't work
CLR P0.7
...

But still: why the direct address adds 2 to PC?


Solution

  • The JMP instruction (actually the SJMP instruction) is a relative jump, so it looks like your your assembler is interpreting the operand literally and using 30h as the relative offset operand in the encoded instruction. Since the offset is relative to the start of the instruction after the SJMP instruction, the relative offset you need to jump to address 30h is 2Eh. If you use a label instead then the assembler calculates the correct relative offset itself.