我的课程笔记始终在其ARM代码片段中使用ADDS和SUBS,而不是我期望的ADD和SUB。例如,这是一个这样的代码段:
__asm void my_capitalize(char *str)
{
cap_loop
LDRB r1, [r0] // Load byte into r1 from memory pointed to by r0 (str pointer)
CMP r1, #'a'-1 // compare it with the character before 'a'
BLS cap_skip // If byte is lower or same, then skip this byte
CMP r1, #'z' // Compare it with the 'z' character
BHI cap_skip // If it is higher, then skip this byte
SUBS r1,#32 // Else subtract out difference to capitalize it
STRB r1, [r0] // Store the capitalized byte back in memory
cap_skip
ADDS r0, r0, #1 // Increment str pointer
CMP r1, #0 // Was the byte 0?
BNE cap_loop // If not, repeat the loop
BX lr // Else return from subroutine
}
例如,此简单代码将字符串中的所有小写英语转换为大写。我在这段代码中无法理解的是为什么他们不使用ADD和SUB命令而不是当前使用的ADDS和SUBS。 ADDS和SUBS命令afaik更新APSR标志NZCV,以供以后使用。但是,如您在上面的片段中所见,未使用更新的值。那么该命令还有其他实用程序吗?
答案 0 :(得分:4)
与比较指令(ADD
,SUB
)不同,算术指令(CMP
,TEQ
等)不会修改状态标志,而比较指令(S
,ADDS
)则通过默认。但是,将SUBS
添加到算术指令(S
,ADDS
等)将根据运算结果更新条件标志。那是对算术指令使用ADD
的唯一目的,因此,如果不检查cf,则没有理由使用CC
代替ADDCC
。>
为了实现不同的目的,有更多代码要附加到指令(link)上,例如ADDCCS
(条件标志C = 0),因此:
ADDS
:如果进位状态位设置为0,则执行操作。
ADD
:如果进位状态位设置为0,然后执行操作,然后更新状态标志(如果C = 1,则状态标志不会被覆盖)。
从循环的角度来看,更新条件标志与否之间没有区别。以ARMv6-M为例,ADD
和ADD
将花费1个周期。
丢弃 SUBS r0, r0, #1
ADDS r0, r0, #2
BNE go_wherever
似乎是一个懒惰的选择,因为在某些情况下 SUBS r0, r0, #1
ADD r0, r0, #2
BNE go_wherever
很有用。更进一步,请考虑以下示例:
ADDS
和
ADD
可能会产生不同的行为。
正如old_timer所指出的,UAL在此主题上变得非常相关。关于统一语言,首选语法是date_filter = date.today() - relativedelta(months=3)
courses = Course.objects.filter(models.Q(courseday__date__gt=date_filter) |
models.Q(courseday__isnull=True)).distinct()
courses = list(courses)
courses.sort(key=lambda x: (x.get_first_date() is None, x.custom_id), reverse=True)
,而不是SELECT
id, values
FROM (
SELECT
*,
row_number() OVER (PARTITION BY id ORDER BY values DESC)
FROM
table
) s
WHERE row_number = 2
(link)。因此,如果要为Thumb和/或ARM(使用UAL)进行汇编,则OP的代码绝对正确(甚至推荐)。
答案 1 :(得分:3)
没有标记更新的ADD在某些cortex-ms上不可用。如果您查看指令集的arm文档(使用汇编语言时通常是个好主意),这些通用案例在armv7-m(cortex-m3,cortex-m4,cortex-m7)上用thumb2扩展后才可用)。 cortex-m0和cortex-m0 +以及通常较宽的兼容性代码(将使用armv4t或armv6-m)没有没有标志的添加选项。所以也许就是这个原因。
另一个原因可能是获得16位指令而不是获得32位指令,但这是一个滑坡,因为它更多地进入了汇编程序及其语法(语法由汇编程序,处理汇编语言的程序定义,不是目标)。例如不是语法统一的气体:
.thumb
add r1,r2,r3
Disassembly of section .text:
00000000 <.text>:
0: 18d1 adds r1, r2, r3
反汇编程序了解现实,但汇编程序却不知道:
so.s: Assembler messages:
so.s:2: Error: instruction not supported in Thumb16 mode -- `adds r1,r2,r3'
但是
.syntax unified
.thumb
adds r1,r2,r3
add r1,r2,r3
Disassembly of section .text:
00000000 <.text>:
0: 18d1 adds r1, r2, r3
2: eb02 0103 add.w r1, r2, r3
在这种情况下不会太滑,但是有了统一的语法,您就开始陷入blahw,blah.w,blah,键入语法的状态,并且不得不回头查看所生成的指令。非统一也有自己的游戏,当然,所有这些都是特定于汇编程序的。
我怀疑他们要么选择唯一的选择,要么使用更小,更兼容的指令,尤其是如果是类或文本,则兼容性越好越好。