字节上的gcc mips有符号算术
我已经将这个简单的代码提供给了gcc字节上的gcc mips有符号算术,c,gcc,mips,C,Gcc,Mips,我已经将这个简单的代码提供给了gcc volatile signed char x, y, z; void test() { x = 0x31; y = x + 3; } 添加Volatile只是为了避免gcc优化(无论如何设置为-O0)。 产生的mips代码为: x: y: z: test(): addiu $sp,$sp,-8 sw $fp,4($sp) move $fp,$sp lui $2,%hi(x) li $3,49 # 0x31
volatile signed char x, y, z;
void test()
{
x = 0x31;
y = x + 3;
}
添加Volatile只是为了避免gcc优化(无论如何设置为-O0)。
产生的mips代码为:
x:
y:
z:
test():
addiu $sp,$sp,-8
sw $fp,4($sp)
move $fp,$sp
lui $2,%hi(x)
li $3,49 # 0x31
sb $3,%lo(x)($2)
lui $2,%hi(x)
lbu $2,%lo(x)($2)
seb $2,$2
andi $2,$2,0x00ff
addiu $2,$2,3
andi $2,$2,0x00ff
seb $3,$2
lui $2,%hi(y)
sb $3,%lo(y)($2)
nop
move $sp,$fp
lw $fp,4($sp)
addiu $sp,$sp,8
j $31
nop
对于(y=x+3),gcc将字节加载为无符号,然后对其进行符号扩展,或者使用0xff?
为什么不简单地使用lb加载它(它应该是扩展它的标志)?
GCC对有符号半字(当然使用0xffff)也有同样的作用。我并不特别擅长读取MIPS程序集,但请注意,您已经使用
-O0
进行了编译,它应该生成未优化的代码。这或多或少意味着代码实现了C抽象机器的精确语义。特别是,
是类型为0x31
int
- 赋值
包括将右侧x=0x31
操作数隐式转换为左侧操作数的类型(int
)有符号字符
也是类型3
int
- 计算
涉及对参数执行整数提升,特别是将x+3
的x
值转换为(signed)signed char
,然后执行加法int
- 将结果赋给
涉及另一个从y
到int
有符号字符的隐式转换
总的来说,询问为什么非优化编译的程序集输出没有您想象的那么有效是没有多大用处的。如果需要更高效的代码,请启用优化。
test:
.seh_endprologue
movb $49, x(%rip)
movzbl x(%rip), %eax
addl $3, %eax
movb %al, y(%rip)
ret
.seh_endproc
.comm z, 1, 0
.comm y, 1, 0
.comm x, 1, 0
.ident "GCC: (GNU) 6.4.0"
你的代码没有问题。gcc/MIPS并不擅长代码生成,这并不令人惊讶,因为它比gcc/Intel得到的关注和关注要少得多。根据我的经验,clang通常比gcc生成更好的MIPS代码