【发布时间】:2018-09-12 18:41:56
【问题描述】:
考虑一下这个 C 函数;
int triangle(int width, int height)
{
return (width * height) / 2;
}
使用 gcc (gcc -m32 -g -c test.c) 编译时会生成以下程序集 (objdump -d -M intel -S test.o)。
test.o: file format elf32-i386
Disassembly of section .text:
00000000 <triangle>:
int triangle(int width, int height)
{
0: 55 push ebp
1: 89 e5 mov ebp,esp
return (width * height) / 2;
3: 8b 45 08 mov eax,DWORD PTR [ebp+0x8]
6: 0f af 45 0c imul eax,DWORD PTR [ebp+0xc]
a: 89 c2 mov edx,eax
c: c1 ea 1f shr edx,0x1f
f: 01 d0 add eax,edx
11: d1 f8 sar eax,1
13: 5d pop ebp
14: c3 ret
我已经知道将整数 n 位向右移动会将其除以 2^n。然而,根据上面的输出,有符号整数似乎被不同地对待(这当然是有道理的)。如果我正确读取程序集输出,则在移位之前将整数的符号位添加到自身。
在右移之前将整数的符号位添加到自身的目的是什么?
【问题讨论】:
-
按照C标准得到正确的结果。
-3 / 2应该是-1但sar改为-2。给负数加一可以解决这个问题。 -
Supercat 指出算术右移(向 -infinity 舍入)对于某些应用程序 (Which is better option to use for dividing an integer number by 2?) 具有有用的属性,而 C 符号除法 (
idiv) 语义向 0 舍入。