程序集分支/循环和功能如何工作

时间:2018-09-11 18:16:30

标签: assembly arm

今天上课时刚刚上了第一堂课。讲师没有解释太多,因为这个想法是我们必须使用书籍来阅读装配的工作原理。我的编程背景是Python和C ++,并且希望将其组装起来,甚至考虑在代码中来回跳动,这是一种牺牲品。

谈论分支时,问题一直困扰着我,这在我的书中似乎没有任何解释。基本上,OP代码B +(EQ,PL等)根据条件和标志进行分支。例如,如果……即是什么,“ BEQ位置”将分支到“位置”。根据我的判断,它使用先前的指示来找出条件(在这种情况下,如果相等(Z = 1))。如果确实如此,那么BEQ会看前一条指令的返回值来评估EQ,例如,我如何做一个循环,使第一个R0(寄存器0)的值为0,然后再发生其他事情,最后我想一个条件分支,检查R0是否为零?

问题2: 我还注意到,如果您要执行某种功能:

WhileLoop:
     MOV R0, R1
     ..bla bla bla
     BEQ WhileLoop

我如何知道BEQ回到“ WhileLoop”?这是否意味着我做的每个功能都需要给它一个不同的名称。也许我不能正确理解功能。

请帮助。

1 个答案:

答案 0 :(得分:1)

您需要阅读ARM文档。您的问题的答案就在那里。

是的,ARM使用标志。与使用标志的任何指令集一样,您需要检查您正在使用或希望使用的每条指令,或者为了获得一般性了解以了解它们是否修改了标志。例如,AND操作设置进位标志是否有意义?不,但是设置零标志有意义吗?当然,这很有用,或者有时他们的TST设置了零标志,而AND却没有,取决于体系结构。

与典型的基于标志的解决方案不同,ARM有一阵子扭曲了,您必须询问指令来设置标志。如果您发现

loop:
  sub r0,#1
  bne loop

不执行您想要的操作,因为根据书面内容(根据arm文档),减法不会触摸任何标志,尤其是我们正在测试的Z标志,但是...

loop:
  subs r0,#1
  bne loop

此代码,减法确实会碰到Z标志。

它允许类似

的事情
  cmp r2,r3
  moveq r1,#1
  bxeq lr
  mov r1,#0
  bx lr

或者说

  if(foo==1)
  {
     bar++;
  }

您通常需要将其实现为

compare with 1
branch if not equal to skip
increment
skip:

所以您有一个管道,也许可以通过分支获取命中

但是

compare with 1
increment if equal

条件执行,条件位。

现在,对于完整尺寸的手臂指令来说,拇指指令是另外一回事了。

随着64位指令集aarch64的使用,整个有条件的东西都消失了,为执行条件而为每条指令烧掉4位是很痛苦的,还不够用。他们本来可以拥有32个通用寄存器,但可能更有用...

所以不确定您要问的功能是什么,首先使用汇编语言,您通常可以使用WhileLoop之类的标签。汇编程序将其转换为正确的指令,虽然Loop不是指令,但它基本上是一个地址,在这种情况下,汇编程序应使用您要求的指令并执行pc相对偏移(不使用固定地址,它会计算标签和beq之间有很多指令,并说如果相等,则向后跳转N条指令)。如果将beq放在某个标签上,并且该标签在另一个模块/对象中定义,则链接器随后必须修补该指令。

就功能而言,因此如果用C编写程序,并且要编写多个指令,是否需要使所有功能名称不同?是的实际上,汇编中没有函数之类的东西,有一些指令给人一种错觉,但它只是一个奇特的标签。但是代表功能的代码,如果要编写其中的7个,则需要为每个标签使用不同的标签。汇编语言与它无关。

gnu汇编程序具有一个有趣的功能,没有理由假定其他汇编语言支持(汇编语言由汇编程序,工具而不是目标(ARM指令集)定义),非常容易针对许多不同的示例进行演示指令集,易于编写的手臂装配,无法在所有受积极支持的装配商之间进行装配。因此,这是一个gnu汇编技巧,可能会或可能不会帮助您使用标签

1:
 subs r0,#1
 beq 1f
 b 1b
1:

您通常只想执行bne,但这可以演示该功能。带有数字的标签是特殊的1f表示标签1:向前,因此下一个标签1:向下翻页。 1b表示1:向后,因此从这一点开始向上阅读页面以查找下一个1:因此您不必做

myfunction:
...
myfunction00:
...
myfunction01:
...
myfunction02:
...

因为您正在努力使中间标签难以处理填充和循环上的简单分支。

您可以选择是特征还是负担,因为它会养成可能特定于工具或不特定于工具的习惯。