程序集分支/循环和函数如何工作
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了程序集分支/循环和函数如何工作相关的知识,希望对你有一定的参考价值。
刚刚在课堂上上了第一堂课。讲师没有解释太多,因为我们必须使用书籍来阅读装配的工作原理。我的编程背景是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”?这是否意味着对于我所做的每一项功能我都需要称它为不同的东西。也许我不正确理解功能。
请帮忙。
您需要阅读ARM文档。你的问题的答案就在那里。
是的ARM使用标志。与使用标志的任何指令集一样,您需要检查您正在使用或希望使用的每条指令,或者用于一般性理解,以查看它们修改的标志是什么。例如,AND操作是否有意义设置进位标志?不,但是设置零标志是否有意义?当然它可能有用,或者有时它们TST设置零标志但AND不依赖于架构。
与典型的flag basd解决方案不同,ARM有一段时间的扭曲,你必须要求ASK指令来设置标志。如果你注意到了
loop:
sub r0,#1
bne loop
没有做你想做的事,因为写的(根据arm文档)减法dos不会触摸任何标志,特别是我们正在测试的Z标志,但......
loop:
subs r0,#1
bne loop
这段代码,减去DOES触摸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,这整个有条件的东西都消失了,每个条件执行指令烧掉四个位有点痛苦,不够用。他们可能有32个通用寄存器,而这可能更有用......
所以不确定你对函数的要求,首先用汇编语言,你经常可以使用像WhileLoop这样的标签。汇编程序将其转换为正确的指令,WhileLoop不是指令,它基本上是一个地址,在这种情况下,汇编程序应该使用您要求的指令并执行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:
...
因为你正在努力制作中间标签来处理东西和循环上的简单分支。
您可以选择是特征还是负担,因为它会创建一种习惯,可能是也可能不是特定于工具的。
以上是关于程序集分支/循环和函数如何工作的主要内容,如果未能解决你的问题,请参考以下文章