【问题标题】:ARM Assembly - Adding two RegistersARM 汇编 - 添加两个寄存器
【发布时间】:2020-02-09 16:35:35
【问题描述】:

我试图通过取消引用前两个寄存器,然后将结果存储在第三个寄存器中,在 ARM 汇编中将两个寄存器相加。

目前我有3个变量和一个函数,如下;

extern void my_function(int* x, int* y, int* total);

int main(void){
   int x = 1;     //R0
   int y = 2;     //R1
   int total = 0; //R2

   while(1){
      my_function(&x, &y, &total);
      printf("\x1b[5;5HTotal = %d, total");
   }
}

还有一个函数,它执行以下操作

对于前两个寄存器,我尝试取消对它们的引用,将它们相加并将结果存储在第三个寄存器中。 这是我的汇编代码;

ldr r4, [r0]    @ Dereference r0, and store the address in R4
ldr r4, [r1]    @ Dereference r1, and store the address in R4
add r2, r0, r1  @ Add r0 & r1 together, and store in R2
str r4, [r2]    @ Store r2 address in r4

当我打印出来时,答案是 0。 我的问题是,当我在汇编中执行前两行时,ldr r4, [r0] 被ldr r4, [r1] 替换,导致输出为0? 他们每个人都需要存储在自己的寄存器中吗? 还是我基本上只是打印出总数(r2)?

【问题讨论】:

  • “当我打印出来时” - 你到底在打印什么? total? r4?
  • 首先是 r0、r1 和 r2 指向变量的指针 (int *x, int *y ...) 还是它们本身包含值? [r0] 间接 r0 不加
  • @ForceBru,我正在尝试打印总变量。
  • 请阅读 arm 文档 ldr r4,[r0] 表示使用 r0 中的值作为地址读取该地址的内存中的 32 位值并将其放入 r4。然后 ldr r4,[r1] 执行相同的操作,但使用 r1 的内容作为地址,并且 r4 现在被新值覆盖,丢失了您在 ldr r4,[r0] 中所做的任何事情。如果 r0 和 r1 是地址,那么 add r2,r0,r1 只是添加地址/指针而不是值。而str r4,[r2]现在将你从r1的地址读取的r4放入r0,r1的地址,此时还没有使用数据值
  • 你的代码不会做你的代码正在做的事情 *(&x + &y) = *y;

标签: c assembly game-boy-advance


【解决方案1】:

切勿在没有文档的情况下启动汇编语言项目。然后实际阅读该文档。

你有一个 C 编译器,所以你可以看看它做了什么,然后找出每条指令在做什么,然后找出你哪里出错了。

void my_function(int* x, int* y, int* total)
{
    *total = *x + *y;
}

可以根据命令行选项生成

my_function:
    ldr r3, [r0]
    ldr r1, [r1]
    add r3, r3, r1
    str r3, [r2]
    bx  lr

您还必须了解用于进行 C/asm 转换的编译器的调用约定。对于这种情况,在 arm 中,r0 是 x 的地址,r1 是 y 的地址,r2 是总的地址。

ldr r4, [r0]    @ read the value of x into r4
ldr r4, [r1]    @ read the value of y into r4 losing/discarding the value of x
add r2, r0, r1  @ add the pointers together destroying the pointer to total
str r4, [r2]    @ store the value of y into a location destroying whatever was there

根据典型的调用约定(编译器可以选择使用/创建他们想要的任何内容,因此您需要了解约定),因为 arm r4 是易失性的,因此您需要将其推入堆栈,您不能破坏其中的内容在你的功能期间。

因为您的程序不修改总变量并且它是 .bss 的一部分,所以引导程序已将总变量归零,而您只是打印出该值,这就是为什么您看到零您的代码与它无关. x 的地址加上 y 的地址成为总地址的几率非常小,基本上为零(但程序可以在它工作的地方制作),所以你的代码再次与总的零值无关.

【讨论】:

  • 啊,现在说得通了。我想我可能会和其他人一起过度使用寄存器。寄存器也很有意义。感谢您的帮助!
  • arm 文档在每条指令的伪代码方面做得很好,我可能会从 armv5 架构参考手册与 armv7-ar 中学习,因为后者有更多的保护和执行模式开销这是该伪代码的一部分。两者都可以工作,并且会显示 ldr r4,[r0] 意味着将 r0 中包含的地址处的值读入寄存器 r4。
  • 不要把它作为你的作业答案。我建议至少在不使用 r3 或更高版本(不是 r4、不是 r5 等)的情况下更改它,只使用 r0、r1、r2,然后它看起来不会是编译器生成的
猜你喜欢
  • 2014-07-06
  • 1970-01-01
  • 1970-01-01
  • 2013-10-21
  • 1970-01-01
  • 1970-01-01
  • 2019-04-10
  • 1970-01-01
相关资源
最近更新 更多