如何运行单行汇编,然后参见[R1]和条件标志

问题描述 投票:0回答:1

我正在尝试自学组装。我在 C、Java 和 Python 方面拥有多年的经验 - 但我在这方面无法取得任何进展,我即将放弃。

所以,我下载了uVision4,并假设我可以编写一个基本的汇编程序:

MOV R1,  #0x7F0E0C2D
MOV R3,  #0x1048B3C5
ADCS  R1, R3, ROR #0x18
END

那么,建立两个变量,做一个操作,完成。当然,请检查输出寄存器和调试器的条件标志。

显然这是不可能的。

我创建文本文件,编写代码,保存为 .asm 文件,然后尝试构建 -

它讨厌那样。

好的,所以我创建一个新项目,添加.asm 文件,

它拒绝了,要求我显然编写整个设备驱动程序来完成一个该死的你好世界。

如何运行简单的几行代码来开始学习?

debugging assembly arm gdb qemu
1个回答
9
投票

相关:如何在 QEMU 上的 GDB 中单步执行 ARM 汇编? 是另一个类似的演练,其中有一个程序可以进行退出系统调用,这样您就可以让它运行而不会崩溃,而不仅仅是单步执行。


我一直在我的 x86 桌面上做这样的事情,使用 gdb 来单步执行代码。通常使用 x86 指令,但也可用于 ARM 交叉开发。使用 ARM GCC

-nostdlib foo.S
进行构建,它应该将默认入口点设置为 .text 部分的开头。不过,如果您没有定义
_start
:

,您确实会收到来自链接器的警告
$ arm-linux-gnueabi-gcc -nostdlib arm-simple.S 
/usr/lib/gcc-cross/arm-linux-gnueabi/5/../../../../arm-linux-gnueabi/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000010098

我必须修改你的源代码才能进行组装。这是我的手臂——简单。S:

.globl _start                                                                                                                                                       
_start:                      @ having a symbol name makes debugging easier

  ldr   R1,  =0x7F0E0C2D       @ ARM immediate constants can't be arbitrary 32-bit values.  Use the ldr reg, =value pseudo-op, which in this case assembles to a PC-relative load from a nearby literal pool.  Often it can use mov reg, #imm or movn reg, #imm
  ldr   R3,  =0x1048B3C5
  ADCS  R1, R3, ROR #0x18

@END  GAS syntax doesn't use ARMASM's end directive.

clang -target arm -mcpu=cortex-15 -c arm-simple.S
可以汇编这个,但即使使用
-static -nostdlib
它也不能链接到静态可执行文件中。 Clang 尝试使用系统
gcc
作为链接器,这不是 ARM 链接器。所以你需要安装交叉工具,至少一个链接器。

然后你可以使用gdb并在第一条指令处设置断点,运行它,并单步执行。

您甚至可以在交叉开发环境中执行此操作,但有一些问题。


在一个终端中,在二进制文件上运行 QEMU,等待调试器连接

$ arm-linux-gnueabi-gcc -g -nostdlib arm-simple.S
$ qemu-arm -g 12345 ./a.out                    # user-mode emulation, waiting for gdb to connect

如果您想具体,请使用

-mcpu=something
表示 gcc,使用
-cpu model
表示 qemu。


在另一个终端中,运行 ARM gdb (在我的例子中,从 Ubuntu 的 gdb-arm-none-eabi 软件包,因为 Ubuntu 没有为 x86 分发 arm-linux-gnueabi-gdb 跨 ARM-gdb 软件包) .

TODO:尝试 gdb-multiarch。 x86 桌面上的常规 gdb 只能调试 x86 二进制文件,所以你绝对不能使用它。

$ arm-none-eabi-gdb ./a.out          # give the gdb client the same binary to read symbols / debug info
(gdb) target remote localhost:12345
(gdb) layout asm
(gdb) layout reg
(gdb) si               # single step by instruction, not source line
(gdb) si

然后gdb显示:

+--Register group: general-----------------------------------------------------------------------------------------------------------------------------------------+
|r0             0x0      0                             r1             0x7f0e0c2d       2131627053            r2             0x0      0                             |
|r3             0x1048b3c5       273200069             r4             0x0      0                             r5             0x0      0                             |
|r6             0x0      0                             r7             0x0      0                             r8             0x0      0                             |
|r9             0x0      0                             r10            0x100ac  65708                         r11            0x0      0                             |
|r12            0x0      0                             sp             0xf6ffea40       0xf6ffea40            lr             0x0      0                             |
|pc             0x100a0  0x100a0 <_start+8>            cpsr           0x10     16                                                                                  |
|                                                                                                                                                                  |
|                                                                                                                                                                  |
|                                                                                                                                                                  |
|                                                                                                                                                                  |
|                                                                                                                                                                  |
|                                                                                                                                                                  |
|                                                                                                                                                                  |
|                                                                                                                                                                  |
|                                                                                                                                                                  |
   ----------------------------------------------------------------------------------------------------------------------------------------------------------------+
   |0x10098 <_start>        ldr    r1, [pc, #4]    ; 0x100a4 <_start+12>                                                                                           |
   |0x1009c <_start+4>      ldr    r3, [pc, #4]    ; 0x100a8 <_start+16>                                                                                           |
  >|0x100a0 <_start+8>      adcs   r1, r1, r3, ror #24                                                                                                             |
   |0x100a4 <_start+12>     svcvc  0x000e0c2d                                                                                                                      |
   |0x100a8 <_start+16>     subne  r11, r8, r5, asr #7                                                                                                             |
   |0x100ac                 andeq  r1, r0, r1, asr #18                                                                                                             |
   |0x100b0                 cmnvs  r5, r0, lsl #2                                                                                                                  |
   |0x100b4                 tsteq  r0, r2, ror #18                                                                                                                 |
   |0x100b8                 andeq  r0, r0, pc                                                                                                                      |
   |0x100bc                 subseq r3, r4, r5, lsl #10                                                                                                             |
   |0x100c0                 tsteq  r8, r6, lsl #6                                                                                                                  |
   |0x100c4                 andeq  r0, r0, r9, lsl #2                                                                                                              |
   |0x100c8                 andeq  r0, r0, r12, lsl r0                                                                                                             |
   |0x100cc                 andeq  r0, r0, r2                                                                                                                      |
   |0x100d0                 andeq  r0, r4, r0                                                                                                                      |
   +---------------------------------------------------------------------------------------------------------------------------------------------------------------+
remote Remote target In: _start                                                                                                              Line: 6    PC: 0x100a0 
(gdb) si

它突出显示了最后修改的寄存器,这非常棒。

不过,它似乎太旧了,无法以符号方式解码标志(PSR)。现代 x86 gdb 可以做到这一点。

对我们源代码中的三个指令之后的后续指令进行反汇编是因为在它们之后内存中有字节,可能包括那些

0x7F0E0C2D
0x1048B3C5
。所以它们会分解成某种东西。 (如果你继续单步执行,执行就会陷入其中,因为我们的代码底部没有退出系统调用。这很好,无论如何我们想在GDB中单步执行它们。)


lldb

参见 LLDB 是否与 gdbserver 兼容(用于调试交叉编译的代码?) - 运行

lldb ./a.out
并使用
gdb-remote
命令:

(lldb) gdb-remote localhost:12345
Process 572699 stopped
* thread #1, stop reason = signal SIGTRAP
    frame #0: 0x00008000 a.out`_start
  ...

(lldb) si    # single-step by instruction

我没有成功使用

platform select remote-gdb-server
/
platform connect connect://localhost:12345
,如 https://lldb.llvm.org/use/remote.html

中所述
© www.soinside.com 2019 - 2024. All rights reserved.