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

Posted

技术标签:

【中文标题】如何运行单行汇编,然后看 [R1] 和条件标志【英文标题】:How to run a single line of assembly, then see [R1] and condition flags 【发布时间】:2017-01-23 01:26:33 【问题描述】:

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

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

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

那么,建立两个变量,做一个运算,大功告成。检查寄存器的输出和调试器的条件标志,当然。

显然,这是不可能的。

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

它讨厌那个。

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

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

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

【问题讨论】:

如果您只想尝试短程序集 sn-ps,为什么不使用 ARMSIM 之类的东西呢? 这确实不会组装,因为您缺少 AREA ... 应该关闭的 END 指令,以及(可能是模降价格式)适当的缩进。 Never assume... 是的,正如迈克尔所说,这种实验几乎正是指令集模拟器的用途。 【参考方案1】:

我一直在我的 x86 桌面上做这样的事情,使用 gdb 单步代码。通常使用 x86 指令,但也适用于 ARM 交叉开发。使用gcc -nostdlib foo.S 构建,它应该将默认入口点设置为 .text 部分的开头。不过,您确实会收到来自链接器的警告:

$ 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

我必须修改你的源代码才能组装。这是我的 arm-simple.S:

.globl _start                                                                                                                                                       
_start:                        @ make debugging easier to have a symbol name                                                                                        

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  This isn't an instruction.

然后你可以使用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 不分发 arm-linux-gnueabi-gdb cross- x86 的 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

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

不过,象征性地解码标志似乎太旧了。现代 x86 gdb 可以做到这一点。

【讨论】:

我没看过,但gdb-multiarch 支持吗? "@END 这不是指令。" - 实际上,它是 armasm 语法中的(必要的)指令,尽管其余代码格式不正确指令和缩进。 @Notlikethat:这个答案正是我想出的单步执行几个 ARM 指令的方法。这至少部分是为了我自己的利益,因为上次我发现我没有写下 qemu 和 gdb cmds!我不是ARM开发人员,只是随便好奇。 OP 提到了 uVision4,但我不知道那是什么,并且 OP 没有说任何关于要求使用它的答案,而不是任何其他方式来构建和运行 ARM 代码。除了 gas 之外,我对 ARM 汇编器一无所知,尽管听到有些使用不同的指令我并不感到惊讶。 哦,当然,这是一个很棒且有用的答案(我一直认为这是可能的,但从未真正尝试过,现在我知道具体方法了!) - 只是想我会尝试澄清 为什么你必须修改 OP 的代码 ;) FWIW,µVision 是 Keil 的微控制器开发套件,它使用 ARM 的 armcc/armasm 工具链——它们与 GCC/GAS 的风格截然不同。

以上是关于如何运行单行汇编,然后看 [R1] 和条件标志的主要内容,如果未能解决你的问题,请参考以下文章

汇编LAHF指令学习 - 使用emu8086

汇编语言addne r4,r4,r1啥意思

了解汇编中的条件代码标志设置

汇编指令

keil5程序怎么看多少指令

arm 汇编 指令看不太懂,高手解释下