我在学组装。我拆解了一个简单的C程序,并用GDB进行了调试。但我注意到的一件事是,值的移动非常频繁。
0x0000555555555231 <+0>: push rbp
0x0000555555555232 <+1>: mov rbp,rsp
0x0000555555555235 <+4>: sub rsp,0x20
0x0000555555555239 <+8>: mov QWORD PTR [rbp-0x18],rdi
0x000055555555523d <+12>: mov QWORD PTR [rbp-0x20],rsi
0x0000555555555241 <+16>: mov rax,QWORD PTR [rbp-0x18]
0x0000555555555245 <+20>: mov rdi,rax
0x0000555555555248 <+23>: call 0x5555555551d9 <get_file_size>
RDI的值在rbp-0x18(<+8>)处移动到堆栈,RSI的值在rbp-0x20(+12)处移动到堆栈。然后,rbp-0x18处的值被移动到rax(+16),该值将再次被移动到rdi(+20)。为什么要这样做?为什么不直接使用rdi,或者至少通过rax(<+16>)直接将rbp-0x18移动到rdi?这可以节省+20时的指令
如果您想学习汇编程序,那么没有启用任何优化的编译没有多大意义。
这里有一个优化如何更改生成的代码的示例。
https://godbolt.org/z/ybdlrz
char *foo(char *dest, const char *src, size_t len)
{
char *savedDest = dest;
size_t index = 0;
if(len)
{
while(--len && (dest[index] = src[index]));
index++;
*dest = 0;
}
return savedDest;
}
foo:
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-24], rdi
mov QWORD PTR [rbp-32], rsi
mov QWORD PTR [rbp-40], rdx
mov rax, QWORD PTR [rbp-24]
mov QWORD PTR [rbp-8], rax
mov QWORD PTR [rbp-16], 0
cmp QWORD PTR [rbp-40], 0
je .L2
.L4:
sub QWORD PTR [rbp-40], 1
cmp QWORD PTR [rbp-40], 0
je .L3
mov rdx, QWORD PTR [rbp-32]
mov rax, QWORD PTR [rbp-16]
add rdx, rax
mov rcx, QWORD PTR [rbp-24]
mov rax, QWORD PTR [rbp-16]
add rax, rcx
movzx edx, BYTE PTR [rdx]
mov BYTE PTR [rax], dl
movzx eax, BYTE PTR [rax]
test al, al
jne .L4
.L3:
add QWORD PTR [rbp-16], 1
mov rax, QWORD PTR [rbp-24]
mov BYTE PTR [rax], 0
.L2:
mov rax, QWORD PTR [rbp-8]
pop rbp
ret
foo:
mov rax, rdi
test rdx, rdx
je .L2
.L4:
dec rdx
je .L3
mov cl, BYTE PTR [rsi]
mov BYTE PTR [rax], cl
test cl, cl
jne .L4
.L3:
mov BYTE PTR [rax], 0
.L2:
ret
程序转移指令 1>无条件转移指令 (长转移) JMP 无条件转移指令 CALL 过程调用 RET/RETF过程返回. 2>条件转移指令 (短转移,-128到+127的距离内) ( 当且仅当(SF XOR OF)=1时,OP1循环控制指令(短转移) LOOP CX不为零时循环. LOOPE/LOOPZ CX不为零且标志Z=1时循环. LOOPNE/LOOPNZ CX不为零且标志Z=0时循环. JCX
我有一个适用于Android和iOS的应用程序。有很多复杂的SQL查询,所以我有一个c层来生成查询,这样就可以在android和ios上使用这种逻辑。 一切都很好,但我注意到在Android系统上,第二类由于某种原因不适合我。 我有一个项目列表,我想按日期排序,然后第二次按标题排序。在iOS上,这很好,在Android系统上,虽然按日期排序,标题不是第二次按标题排序。 查询和数据库文件在两个平台上
下面是我的c函数: 如果str[i]=='a',则将设置zflag,je.L5将接受分支。如果str[i]!='a',则将清除zflag。je.L5不会拿树枝。 为什么编译器在cmpb指令后生成两行额外的代码?
问题内容: 这个问题已经在这里有了答案 : 在排序时访问列表 (2个答案) 6年前关闭。 我想就地对列表进行排序,并尝试在排序过程中(功能内)使用列表本身。我发现列表本身似乎是空的。 所以我尝试了: 并得到 有什么解释吗? 问题答案: 从源代码: 并从Mutable Sequence Types文档中 : CPython实现细节 :在对列表进行排序时,尝试使列表变异甚至检查的效果是不确定的。Pyt
我正在创建一个应用程序,用户在其中输入 7-10 个数值。然后,条目用于一个相当分层的公式,该公式向用户返回结果。两个值给我带来了麻烦,并产生了一个我无法弄清楚的数字。 从微调器中选择一个条目,因为只有4种可能的选择: 此选项不仅用于等式,还用于确定是否需要额外的信息。 获得IHCValue: 如果用户从此下拉列表中选择“2”,则下一个活动将要求 ,也用于等式的一部分: 获取FISHEntry:
我正在遵循斯普林特启动的15分钟指南(gs-关系-数据-访问) 因此,该指南使用H2数据库。现在我通过在运行时提供JAR来改变这一点,以使用DB2。 改良build.gradle 现在应用程序失败了,抱怨没有找到JDBCTemplateBean定义或类似的东西。 所以现在我进一步修改了build.gradle注释掉sping-jdbc,并使用sping-boo-starter-jdbc 现在,应用