unsigned char fun ( unsigned char a, unsigned char b )
{
return(a+b);
}
Disassembly of section .text:
0000000000000000 <fun>:
0: 8d 04 3e lea (%rsi,%rdi,1),%eax
3: c3 retq
Disassembly of section .text:
00000000 <fun>:
0: e0800001 add r0, r0, r1
4: e20000ff and r0, r0, #255 ; 0xff
8: e12fff1e bx lr
Disassembly of section .text:
00000000 <fun>:
0: 1840 adds r0, r0, r1
2: b2c0 uxtb r0, r0
4: 4770 bx lr
Disassembly of section .text:
00000000 <fun>:
0: 952e add x10,x10,x11
2: 0ff57513 andi x10,x10,255
6: 8082 ret
这是一个编译器选择,因此您需要与编译器作者讨论它,而不是堆栈溢出。编译器需要在功能上实现高级语言,因此,在这些情况下,所有这些都有32位GPRs,选择是屏蔽每个操作还是至少在值留待以后使用之前屏蔽,还是假设寄存器脏了,需要在使用之前屏蔽它,或者您是否有架构功能,如eax可以在较小的部分ax、al中访问,并围绕此进行设计?只要它在功能上起作用,任何解决方案都是完美的。
一个编译器可能会选择将al用于8位操作,另一个编译器可能会选择eax(从性能角度来看,eax可能更有效,您可以阅读关于该主题的内容),在这两种情况下,您都必须为rax/eax/ax寄存器中的剩余位进行设计,而不是稍后再对其进行oops并使用较大的寄存器。
但要签字:
signed char fun ( signed char a, signed char b )
{
return(a+b);
}
Disassembly of section .text:
0000000000000000 <fun>:
0: 8d 04 3e lea (%rsi,%rdi,1),%eax
3: c3 retq
Disassembly of section .text:
00000000 <fun>:
0: e0800001 add r0, r0, r1
4: e1a00c00 lsl r0, r0, #24
8: e1a00c40 asr r0, r0, #24
c: e12fff1e bx lr
强制它处理此函数中的大小
signed char fun ( signed char a, signed char b )
{
if((a+b)>200) return(1);
return(0);
}
Disassembly of section .text:
0000000000000000 <fun>:
0: 40 0f be f6 movsbl %sil,%esi
4: 40 0f be ff movsbl %dil,%edi
8: 01 f7 add %esi,%edi
a: 81 ff c8 00 00 00 cmp $0xc8,%edi
10: 0f 9f c0 setg %al
13: c3 retq
Disassembly of section .text:
00000000 <fun>:
0: e0800001 add r0, r0, r1
4: e35000c8 cmp r0, #200 ; 0xc8
8: d3a00000 movle r0, #0
c: c3a00001 movgt r0, #1
10: e12fff1e bx lr
因为arm设计知道传入的值已被剪裁,这比他们选择不剪裁的值大,可能是因为我将其保留为已签名。但在x86的情况下,因为它们没有在退出时进行剪辑,所以在进入操作时进行了剪辑。
unsigned char fun ( unsigned char a, unsigned char b )
{
if((a+b)>200) return(1);
return(0);
}
Disassembly of section .text:
00000000 <fun>:
0: e0800001 add r0, r0, r1
4: e35000c8 cmp r0, #200 ; 0xc8
8: d3a00000 movle r0, #0
c: c3a00001 movgt r0, #1
10: e12fff1e bx lr
现在我不同意,因为例如0xFF+0x01=0x00,它不大于200,但这段代码将以大于200的形式传递它。他们还在无符号比较中使用有符号小于和大于。
unsigned char fun ( unsigned char a, unsigned char b )
{
if(((unsigned char)(a+b))>200) return(1);
return(0);
}
00000000 <fun>:
0: e0800001 add r0, r0, r1
4: e20000ff and r0, r0, #255 ; 0xff
8: e35000c8 cmp r0, #200 ; 0xc8
c: 93a00000 movls r0, #0
10: 83a00001 movhi r0, #1
14: e12fff1e bx lr
啊,这是一些C语言推广活动。(就像浮动f;f=f+1.0;vs f=f+1.0F;)
Disassembly of section .text:
0000000000000000 <fun>:
0: 01 fe add %edi,%esi
2: 40 80 fe c8 cmp $0xc8,%sil
6: 0f 97 c0 seta %al
9: c3 retq
为什么GCC使用EAX而不是AL?
为什么djgpp只使用AL?
是性能问题吗?
这些是编译器设计的选择,不是问题,不一定是性能问题,而是关于如何使用目标指令集实现高级语言的总体编译器设计。每个编译器都可以自由地按照自己的意愿进行操作,没有理由期望gcc、clang、djgpp和其他编译器具有相同的设计选择,也没有理由期望gcc版本x.x.x和y.y.y具有相同的设计选择,因此,如果您回溯得足够远,那么可能是不同的,也许不是(如果他们有,那么提交可能会解释“为什么”的问题,或者从那时起开发团队的电子邮件会涵盖它)。