Assembly 在arm ONE eabi gdb模拟器中,来自程序入口点的ldr似乎给出了无意义的结果

Assembly 在arm ONE eabi gdb模拟器中,来自程序入口点的ldr似乎给出了无意义的结果,assembly,arm,gdb,Assembly,Arm,Gdb,我正在学习为裸金属覆盆子pi编写ARM汇编程序。 我在x86机器上运行arm none eabi gdb进行调试。 arm none eabi gdb附带的模拟器在以下简单程序中的行为与我预期的不同: .section ".text.startup" .global _start _start: nop nop nop ldr r0, =_start ldr r2, [r0] ldr r3, [r0, #4] l

我正在学习为裸金属覆盆子pi编写ARM汇编程序。
我在x86机器上运行arm none eabi gdb进行调试。
arm none eabi gdb
附带的模拟器在以下简单程序中的行为与我预期的不同:

.section ".text.startup"

.global _start

_start:
    nop
    nop
    nop
    ldr     r0, =_start
    ldr     r2, [r0]
    ldr     r3, [r0, #4]
    ldr     r4, [r0, #8]
我希望
nop
的代码加载到寄存器
r2
r3
r4
。然而,当我编译程序时

$ arm-none-eabi-gcc -mfloat-abi=hard -nostartfiles -mfpu=neon-vfpv4 -march=armv7-a -mtune=cortex-a7 -O0 test.S -o kernel.elf
得到

$ arm-none-eabi-objdump -S kernel.elf

kernel.elf:     file format elf32-littlearm


Disassembly of section .text:

00004000 <_start>:
    4000:   e320f000    nop {0}
    4004:   e320f000    nop {0}
    4008:   e320f000    nop {0}
    400c:   e59f0008    ldr r0, [pc, #8]    ; 401c <_start+0x1c>
    4010:   e5902000    ldr r2, [r0]
    4014:   e5903004    ldr r3, [r0, #4]
    4018:   e5904008    ldr r4, [r0, #8]
    401c:   00004000    .word   0x00004000
$arm none eabi objdump-S kernel.elf
kernel.elf:文件格式elf32 littlearm
第节的分解。正文:
00004000 :
4000:e320f000 nop{0}
4004:e320f000 nop{0}
4008:e320f000 nop{0}
400c:e59f0008 ldr r0,[pc,#8];401c
4010:e5902000 ldr r2[r0]
4014:e5903004 ldr r3[r0,#4]
4018:e5904008 ldr r4[r0,#8]
401c:00004000.字0x00004000
并在模拟机内的
arm none eabi gdb
中运行,寄存器
r3
r4
加载了
0xe320f000
,这是正确的。
但是,
r2
加载了
0xe7ffdefe
,它似乎不在任何地方

我有
arm-none-eabi-gdb
7.8.1版和
arm-none-eabi-gcc
4.8.3版。这是模拟器中的错误还是我遗漏了一些明显的东西


另外,我尝试将入口点更改为
0x4000
,而不是链接脚本中的默认
0x8000
。问题仍然存在,因此模拟器无法从入口点内存地址正确加载?

是否在
\u start:
处设置了断点
0xe7ffdefe
可能是软件断点的机器指令,GDB用它重写了第一个
nop
,以实现断点

您可以使用
\u start:mov edi,[rel\u start]
在x86上复制此命令,RDI的低字节将是
0xcc
int3
)或
0x8b
mov r32,r/m32
)取决于您是否在
\u start
设置了断点


GDB不会试图伪造代码来阻止它看到软件断点。您可以让GDB使用硬件断点来解决这个问题。使用
hbreak
而不是
break
()

但是GDB确实在
x/i
disas
GDB命令中隐藏了这一点,呈现出未修改代码字节的幻觉


顺便说一句,您可以使用
starti
运行程序,但在第一条指令执行之前停止。(即,在入口点设置一个临时断点,其优点是即使入口点没有标签也可以工作。)


然后您可以执行一个步骤(也不涉及设置软件断点),代码将按预期执行。

谢谢!这很有道理。我确实在
\u start
设置了一个断点,然后像傻瓜一样反复检查
x/x 0x8000
。顺便说一句,我检查了
starti
在我的
arm-none-eabi-gdb
7.8.1版中不可用,但在8.2.1版中可用。