我正在学习为裸机树莓派编写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-gdb
中的模拟器中运行它,寄存器r3
和r4
装入了0xe320f000
,这是正确的。
但是r2
已加载0xe7ffdefe
,似乎并非来自任何地方。
我有arm-none-eabi-gdb
版本7.8.1和arm-none-eabi-gcc
版本4.8.3。这是模拟器中的错误还是我遗漏了一些明显的东西?
P.s。我试图在链接脚本中将入口点更改为0x4000
,而不是默认的0x8000
。问题仍然存在,因此模拟器无法从入口点内存地址正确加载吗?
答案 0 :(得分:1)
您在_start:
处设置了断点吗? 0xe7ffdefe
可能是GDB覆盖了第一个nop
的软件断点的机器指令,以实现断点。
您可以使用_start: mov edi, [rel _start]
在x86上重现它,RDI的低字节将为0xcc
(int3
)或0x8b
({{1的操作码}}),具体取决于您是否在mov r32, r/m32
处设置了断点。
GDB不会伪造自己读取的代码以阻止其看到软件断点。您可以让GDB使用硬件断点来解决此问题。使用_start
代替hbreak
(https://sourceware.org/gdb/onlinedocs/gdb/Set-Breaks.html)
但是GDB确实从break
或x /i
GDB命令中隐藏了这一点,呈现出未修改的代码字节的错觉。
顺便说一句,您可以使用disas
运行程序,但在执行第一条指令之前就停止。 (即,在入口点设置一个临时断点,其优点是即使入口点没有标签也可以使用。)
然后,您可以单步执行(也无需设置SW断点),您的代码将按预期执行。