当我尝试在 Armv8 程序集中分配数组时执行冻结

Posted

技术标签:

【中文标题】当我尝试在 Armv8 程序集中分配数组时执行冻结【英文标题】:Execution freezes when I try to allocate Array in Armv8 assembly 【发布时间】:2020-11-24 17:13:54 【问题描述】:

所以我正在使用 assemply 编程,这只是一个简单的代码,因此我可以学习如何分配数组以便以后在 NEON 编程中使用它们。

ASM_FUNC(FPE)
.data
.balign 8

array: .skip 80 
array1: .word 10,20,30,40

.text

ldr x0,=array
mov x1,#10

check: 
      cmp x1,#1
      bne loop
      b exit

loop:
      str x1,[x0],#8 //Stores the value in x1 into x0 and moves the address +8 bytes
      sub x1,x1,#1   //x1--
      b check


exit:
      mov x0,#11
          ret

因此,对某些部分进行了注释,因此我可以尝试查找代码中断的位置(我的系统上没有调试)。 我开始评论计算部分,最后在 ret 之前添加了一个 mov x0,#11 以查看问题是否出在计算上。事实证明不是。 当我取消对数组的注释时: .skip 80 和 ldr x0,=array 如果没有响应,我的应用程序就会停留在那里。

谁能告诉我我做错了什么? 我在 armv8 程序集上使用 A64

从这个c程序调用入口点:

void  PocAsm_EntryPoint ( )
    
    
    
          Print(L"========== ASM ==========\n");
       
        
          UINT32 fff = FPE();
          Print(L" %d \n",fff);
        
          Print(L"=========== ASM ===========\n");
        
          Print(L"Test version 0.24 \n");
      return 0;
    

很遗憾,我没有找到 Print 的定义,所以我很抱歉

【问题讨论】:

您在 64 位机器上,64 位值是 8 个字节,而不是 4 个。如果要存储 32 位值,您应该存储 w1 而不是 @987654324 @. 另外,您的代码需要一个入口点。你是如何组装和链接这个的?正如所写的那样,所有的可执行代码都在.data 部分;它应该在.text 感谢您的回答。我修复了代码并在问题中对其进行了编辑,但仍然得到相同的结果:应用程序冻结。我正在使用基于 c 的 pre-OS UEFI。我还将编辑入口点 您能否在问题中提供有关您的算法的更多详细信息?它到底应该做什么?您想“分配”数组(恕我直言,这已经由 .word 和 .skip 指令完成),还是您的意思是“初始化”?谢谢。 我不确定你的链接器和加载器是如何工作的,但是如果你将ASM_FUNC(FPE) 移动到.text 之后会发生什么?我想知道它是否将标签放在数组的位置,以便您执行数组中的数据而不是您想要的代码。 【参考方案1】:

这是试图回答以下问题:FPE() 函数是否按预期工作,同时使用标准工具(例如 qemu-system-aarch64GDB)从等式中删除所有其他内容。

FPE() 函数的代码将为 Cortex-A53 qemu-virt 机器编译。

先决条件:

qemu-system-aarch64 已安装:

Ubuntu 20.04sudo apt-get install qemu-system-armWindows 10:从here 下载并安装qemu-w64-setup-20201120.exe 安装程序。

安装了Cortex-Aaarch64-none-elf 工具链。它可以从ARM WEB site 下载。有适用于 Linux 和 Windows 10 的版本。

FPE.s:

        .arch armv8-a
        .file   "FPE.s"

        .data
        .balign 8
        .globl array
array:  .skip 80 
array1: .word 10,20,30,40

        .text
        .align  2
        .globl FPE
FPE:
        ldr x0,=array
        mov x1,#10

check: 
        cmp x1,#1
        bne loop
        b exit

loop:
        str x1,[x0],#8  //Stores the value in x1 into x0 and moves the address +8 bits
        sub x1,x1,#1    //x1--
        b check

exit:
        mov x0,#11
        ret
        .end

startup.s:

                .title startup64.s
                .arch armv8-a
                .text
                .section .text.startup,"ax"    
                .globl _start
_start:
                ldr x0, =__StackTop
                mov sp, x0
                bl FPE
wait:           wfe
                b wait
               .end

建筑:

我们将为 qemu-virt 机器构建FPE.elf(RAM 开始于0x40000000):

/opt/arm/9/gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin/aarch64-none-elf-gcc -nostdlib -nostartfiles -ffreestanding -g -Wl,--defsym,__StackTop=0x40010000 -Wl,--section-start=.text=0x40000000 -o FPE.elf startup.s FPE.s

调试:

在 shell 中启动 qemu:

/opt/qemu-5.1.0/bin/qemu-system-aarch64  -semihosting -m 1M -nographic -serial telnet::4444,server,nowait -machine virt,gic-version=2,secure=on,virtualization=on -S -gdb tcp::1234,ipv4 -cpu cortex-a53 -kernel FPE.elf

开始GDB:

opt/arm/9/gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin/aarch64-none-elf-gdb  --quiet -nx -ex 'target remote localhost:1234' -ex 'load' --ex 'b _start' -ex 'b exit' FPE.elf

GDB 应该开始:

Reading symbols from FPE.elf...
Remote debugging using localhost:1234
_start () at startup.s:7
7                       ldr x0, =__StackTop
Loading section .text, size 0x50 lma 0x40000000
Loading section .data, size 0x60 lma 0x40010050
Start address 0x40000000, load size 176
Transfer rate: 85 KB/sec, 88 bytes/write.
Breakpoint 1 at 0x40000000: file startup.s, line 7.
Breakpoint 2 at 0x40000040: file FPE.s, line 28.

从此时起,stepip/x $x0x/10g 0x40010050 命令可用于监视程序行为,直到它到达exit 标签为止。

我们将在这里显示数组中开始和退出断点处的 10 个元素:

gdb) x/10g 0x40010050
0x40010050:     0       0
0x40010060:     0       0
0x40010070:     0       0
0x40010080:     0       0
0x40010090:     0       0
(gdb) continue
Continuing.

Breakpoint 2, exit () at FPE.s:28
28              mov x0,#11
(gdb) x/10g 0x40010050
0x40010050:     10      9
0x40010060:     8       7
0x40010070:     6       5
0x40010080:     4       3
0x40010090:     2       0

从这一点单步执行表明程序从其执行中正确返回:

(gdb) stepi
29              ret
(gdb) stepi
wait () at startup.s:10
10      wait:           wfe
(gdb) stepi
11                      b wait
(gdb) stepi
10      wait:           wfe

因此问题的答案是:是的,FPE() 函数的代码工作正常。

完全相同的过程可以在 Windows 10 上运行,这只是调整用于运行 aarch64-none-elf-gccqemu-system-aarch64GDB 的三个命令的问题。


将您的目标文件转储与我测试的文件进行比较可能有助于理解问题:

/opt.arm/9/gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin/aarch64-none-elf-as -o FPE.o FPE.s
/opt/arm/9/gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin/aarch64-none-elf-objdump -D FPE.o 

FPE.o:     file format elf64-littleaarch64


Disassembly of section .text:

0000000000000000 <FPE>:
   0:   58000140        ldr     x0, 28 <exit+0x8>
   4:   d2800141        mov     x1, #0xa                        // #10

0000000000000008 <check>:
   8:   f100043f        cmp     x1, #0x1
   c:   54000041        b.ne    14 <loop>  // b.any
  10:   14000004        b       20 <exit>

0000000000000014 <loop>:
  14:   f8008401        str     x1, [x0], #8
  18:   d1000421        sub     x1, x1, #0x1
  1c:   17fffffb        b       8 <check>

0000000000000020 <exit>:
  20:   d2800160        mov     x0, #0xb                        // #11
  24:   d65f03c0        ret
        ...

Disassembly of section .data:

0000000000000000 <array>:
        ...

0000000000000050 <array1>:
  50:   0000000a        .inst   0x0000000a ; undefined
  54:   00000014        .inst   0x00000014 ; undefined
  58:   0000001e        .inst   0x0000001e ; undefined
  5c:   00000028        .inst   0x00000028 ; undefined

转储最小示例的完整 ELF 文件将给出:

opt/arm/9/gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf/bin/aarch64-none-elf-objdump -D FPE.elf

FPE.elf:     file format elf64-littleaarch64


Disassembly of section .text:

0000000040000000 <_start>:
    40000000:   580000c0        ldr     x0, 40000018 <wait+0xc>
    40000004:   9100001f        mov     sp, x0
    40000008:   94000006        bl      40000020 <FPE>

000000004000000c <wait>:
    4000000c:   d503205f        wfe
    40000010:   17ffffff        b       4000000c <wait>
    40000014:   00000000        .inst   0x00000000 ; undefined
    40000018:   40010000        .inst   0x40010000 ; undefined
    4000001c:   00000000        .inst   0x00000000 ; undefined

0000000040000020 <FPE>:
    40000020:   58000140        ldr     x0, 40000048 <exit+0x8>
    40000024:   d2800141        mov     x1, #0xa                        // #10

0000000040000028 <check>:
    40000028:   f100043f        cmp     x1, #0x1
    4000002c:   54000041        b.ne    40000034 <loop>  // b.any
    40000030:   14000004        b       40000040 <exit>

0000000040000034 <loop>:
    40000034:   f8008401        str     x1, [x0], #8
    40000038:   d1000421        sub     x1, x1, #0x1
    4000003c:   17fffffb        b       40000028 <check>

0000000040000040 <exit>:
    40000040:   d2800160        mov     x0, #0xb                        // #11
    40000044:   d65f03c0        ret
    40000048:   40010050        .inst   0x40010050 ; undefined
    4000004c:   00000000        .inst   0x00000000 ; undefined

Disassembly of section .data:

0000000040010050 <__data_start>:
        ...

00000000400100a0 <array1>:
    400100a0:   0000000a        .inst   0x0000000a ; undefined
    400100a4:   00000014        .inst   0x00000014 ; undefined
    400100a8:   0000001e        .inst   0x0000001e ; undefined
    400100ac:   00000028        .inst   0x00000028 ; undefined

【讨论】:

好的。所以我做了一些测试,看看代码卡在哪一行。我评论了整个代码,只留下了array: .skip 80 mov x0,#10,它卡住了比我试过的:array1: .word 10,20,30,40 mov x0,#10 再次,卡住了。这些台词有什么问题? 通过一些测试,您的意思是使用 GDB 和 QEMU 吗?顺便说一句,您没有告诉您正在使用哪些编译器/汇编器软件。你能提供 FPE.o 的反汇编吗? (假设您的汇编代码在 FPE.s 中)?你能创建一个类似于我的最小示例吗?这将允许您使用 qemu 和 GDB 调试您的代码,恕我直言,这是找出不工作的最佳方法。 我用FPE.o 目标文件的objdump 输出扩充了我的答案,如果您使用自己的目标文件的转储来扩充答案,这将非常有用:它们应该非常类似。 非常感谢您的努力和帮助。经过一些测试,我意识到错误只是分配了向量。我可能做错了什么?你能给我提供一个非常简单的最小工作代码,它将一个包含 10 个数字的数组分配到 x0 寄存器中吗?这是我在代码中面临的大问题。非常感谢 您没有回答我的任何问题,也没有评论我组装/调试的代码是否是您试图使工作的代码。在这种情况下,我想我无法提供更多帮助。

以上是关于当我尝试在 Armv8 程序集中分配数组时执行冻结的主要内容,如果未能解决你的问题,请参考以下文章

在 ARMv8 程序集中将范围限制在 0 到 9 之间的随机数是啥?

ARMv8 A64 程序集中的立即数范围

当我尝试重新分配()结构指针数组时,为啥我的 C 程序会崩溃?

在冻结的应用程序中使用请求时出错

ARMv8 程序集,调用子程序时遇到总线错误

当我尝试 JsonConvert.DeserializeObject <T> 时,我的 xamarin 应用程序冻结