Search code examples
assemblyembeddedpicgpasm

How to get the high (over 16 bits) part of an address from a label in gpasm


I want to retrieve the high (over 16 bits) part of an address from a label in gpasm code.

Here is my small example test.asm:

    LIST P=PIC18F46Q10
    ;LIST P=PIC18F47J13

    ORG 0

    MOVLW TEST_LOCATION & 0xFF
    MOVWF 0x500, A
    MOVLW (TEST_LOCATION >> 8) & 0xFF
    MOVWF 0x501, A
    MOVLW (TEST_LOCATION >> 16) & 0xFF
    MOVWF 0x502, A

JUST_LOOP
    BRA JUST_LOOP

    ORG 0x12468
TEST_LOCATION
    DB 0xDE, 0xAD, 0xBE, 0xEF

    END

The aim of this code is to store the address of TEST_LOCATION (0x12468) to some part of the RAM.

Assembler version:

D:\Temp>gpasm -v
gpasm-1.5.2 #1325 (Jan 30 2022)

Assemble command:

gpasm test.asm

Here is a part of resulting test.lst:

LOC    OBJECT CODE    LINE  SOURCE TEXT
  VALUE

                      00001         LIST P=PIC18F46Q10
                      00002         ;LIST P=PIC18F47J13
                      00003 
000000                00004         ORG 0
                      00005 
000000 0E68           00006         MOVLW TEST_LOCATION & 0xFF
Message[1302]: RAM Bank undefined in this chunk of code. Ensure that bank bits are correct. Assuming bank 5 from now on.
000002 6E00           00007         MOVWF 0x500, A
000004 0E24           00008         MOVLW (TEST_LOCATION >> 8) & 0xFF
000006 6E01           00009         MOVWF 0x501, A
000008 0E00           00010         MOVLW (TEST_LOCATION >> 16) & 0xFF
00000A 6E02           00011         MOVWF 0x502, A
                      00012 
00000C                00013 JUST_LOOP
00000C D7FF           00014         BRA JUST_LOOP
                      00015 
012468                00016         ORG 0x12468
012468                00017 TEST_LOCATION
Warning[220]: Address exceeds maximum range for this processor. BADROM_START: 0x010000 <= Bad address: 0x012468 <= BADROM_END: 0x30FFFF
Warning[220]: Address exceeds maximum range for this processor. BADROM_START: 0x010000 <= Bad address: 0x012469 <= BADROM_END: 0x30FFFF
Warning[220]: Address exceeds maximum range for this processor. BADROM_START: 0x010000 <= Bad address: 0x01246A <= BADROM_END: 0x30FFFF
Warning[220]: Address exceeds maximum range for this processor. BADROM_START: 0x010000 <= Bad address: 0x01246B <= BADROM_END: 0x30FFFF
012468 ADDE EFBE      00018         DB 0xDE, 0xAD, 0xBE, 0xEF
                      00019 
                      00020         END

You can see the middle part 0x24 and the lower part 0x68 from the address 0x12468 are correctly embed into the instructions, but the high part 0x01 didn't get embed and zero is stored instead.

I thought that this may be because PIC18F46Q10, which has 64k-byte program ROM and doesn't have storage at 0x12468, is selected, so I tried switching to PIC18F47J13, which has 128k-byte program ROM. However, the high part still got embed as zero.

A part of resulting test.lst for this case:

LOC    OBJECT CODE    LINE  SOURCE TEXT
  VALUE

                      00001         ;LIST P=PIC18F46Q10
                      00002         LIST P=PIC18F47J13
                      00003 
000000                00004         ORG 0
                      00005 
000000 0E68           00006         MOVLW TEST_LOCATION & 0xFF
Message[1302]: RAM Bank undefined in this chunk of code. Ensure that bank bits are correct. Assuming bank 5 from now on.
000002 6E00           00007         MOVWF 0x500, A
000004 0E24           00008         MOVLW (TEST_LOCATION >> 8) & 0xFF
000006 6E01           00009         MOVWF 0x501, A
000008 0E00           00010         MOVLW (TEST_LOCATION >> 16) & 0xFF
00000A 6E02           00011         MOVWF 0x502, A
                      00012 
00000C                00013 JUST_LOOP
00000C D7FF           00014         BRA JUST_LOOP
                      00015 
012468                00016         ORG 0x12468
012468                00017 TEST_LOCATION
012468 ADDE EFBE      00018         DB 0xDE, 0xAD, 0xBE, 0xEF
                      00019 
                      00020         END

What should I do to get the high part of the address 0x01 from the label TEST_LOCATION with gpasm?

Writing 0x01 directly without using TEST_LOCATION can be a workaround, but it doesn't look nice.


Solution

  • If you use provided operators, you can obtain the bytes of the address:

        MOVLW LOW TEST_LOCATION
        MOVWF 0x500, A
        MOVLW HIGH TEST_LOCATION
        MOVWF 0x501, A
        MOVLW UPPER TEST_LOCATION
        MOVWF 0x502, A