代码之家  ›  专栏  ›  技术社区  ›  zach

如何使用avr gcc生成准确的列表文件?

  •  0
  • zach  · 技术社区  · 5 年前

    我正在尝试为avr模拟器创建一个接口。接口的输入是avr汇编,由接口编译。在编译过程中,我想为每个汇编指令生成一个包含4项内容的文件:原始汇编文件中的行号、汇编指令在内存中的位置、汇编指令的操作码和原始汇编指令。

    到目前为止,我已经成功地使用了一个基本的测试程序,但是当我开始使用包含分支的程序进行测试时,我注意到我生成的列表文件和对象文件都不准确:分支不是分支到标签,而是分支到pc+1。从 this question 我相信这是一个链接器的问题。

    给定此测试文件:

    .global main
    main:
        ldi r16, 10
        ldi r17, 0
    loop: 
        add r17, r16
        dec r16
        cpi r16, 0
        brne loop
        cpi r17, 50
        brge grtr
        ldi r18, 1
        rjmp done
    grtr:
        ldi r18, 2
    done:
        mov r0, r18
    
    

    我用来组装它的原始命令是:

    avr-gcc -Wa,-alhns -Wa,-L -mmcu=atmega2560 test.s -c -o test.o > test.lst
    

    我使用avr objcopy生成的对应hex文件是

    :100000000AE010E0100F0A950030>01F4123304F4F6
    :0800100021E000C022E0022EF5
    :00000001FF
    

    列表文件是:

       1                .global main
       2                main:
       3 0000 0AE0              ldi r16, 10
       4 0002 10E0              ldi r17, 0
       5                loop: 
       6 0004 100F              add r17, r16
       7 0006 0A95              dec r16
       8 0008 0030              cpi r16, 0
       9 000a 01F4              brne loop
      10 000c 1233              cpi r17, 50
      11 000e 04F4              brge grtr
      12 0010 21E0              ldi r18, 1
      13 0012 00C0              rjmp done
      14                grtr:
      15 0014 22E0              ldi r18, 2
      16                done:
      17 0016 022E              mov r0, r18
      18                
    DEFINED SYMBOLS
                  test.s:2      .text:0000000000000000 main
                  test.s:5      .text:0000000000000004 loop
                  test.s:14     .text:0000000000000014 grtr
                  test.s:16     .text:0000000000000016 done
    
    NO UNDEFINED SYMBOLS
    
    

    如果我用

    avr-gcc -Wa,-alhns -Wa,-L -mmcu=atmega2560 test.s -o test.o > test.lst
    

    我生成包含整个中断向量表的十六进制

    :100000000C9472000C947E000C947E000C947E0084
    :100010000C947E000C947E000C947E000C947E0068
    :100020000C947E000C947E000C947E000C947E0058
    :100030000C947E000C947E000C947E000C947E0048
    :100040000C947E000C947E000C947E000C947E0038
    :100050000C947E000C947E000C947E000C947E0028
    :100060000C947E000C947E000C947E000C947E0018
    :100070000C947E000C947E000C947E000C947E0008
    :100080000C947E000C947E000C947E000C947E00F8
    :100090000C947E000C947E000C947E000C947E00E8
    :1000A0000C947E000C947E000C947E000C947E00D8
    :1000B0000C947E000C947E000C947E000C947E00C8
    :1000C0000C947E000C947E000C947E000C947E00B8
    :1000D0000C947E000C947E000C947E000C947E00A8
    :1000E0000C947E0011241FBECFEFD1E2DEBFCDBF46
    :1000F00000E00CBF0E9480000C948C000C94000067
    :100100000AE010E0100F0A950030E1F7123314F402
    :0C01100021E001C022E0022EF894FFCF95
    :00000001FF
    

    但很明显,分支的十六进制现在是准确的。问题是,列表文件仍然和以前一样。不仅分支的操作码是错误的,而且现在汇编指令的内存位置也是错误的。

    我在生成这个列表文件时犯了什么错误?理想情况下,我希望生成一个具有正确操作码且不包括中断向量表或包括中断向量表且具有正确的汇编指令内存位置的操作码。

    提前谢谢。

    0 回复  |  直到 5 年前
        1
  •  1
  •   Peter Cordes    5 年前

    另一种可能的方法是使用debug info汇编+link,然后使用 objdump 使用源代码+反汇编输出模式获取机器代码和地址+原始源代码行。

    这样可以使链接的可执行文件正确填充分支目标。

    你可以用 objdump -D 要“反汇编”可执行文件的非代码部分,所以您可以使用它来获取IVT的hexdump。