assembly - 将有符号整数除以 2 编译为复杂的汇编输出,而不仅仅是移位
问题描述
考虑这个 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 除法运算符的预期结果相比,负数将具有不同的结果。
一个例子是 -1:右移 1 仍然给出 -1,但 C 运算符/ 2
给出 0。
所以额外的代码是对这种效果的修正。如果您不需要,请使用无符号或显式移位(但第二个选项的可移植性较差)。
推荐阅读
- python - Code takes a lot of time to run for large numbers
- php - BitExchange 错误(加密货币兑换脚本)
- netezza - DBeaver 和 Nettezza
- powershell - 等待..直到在 ForEach
- azure - 当本地具有 .local 后缀时,如何将本地域与 Azure AD 同步
- python - Python:生成一个包含 5 列的多值真值表,其中每列可以取一组特定的值
- javascript - Javascript .getDate() : getting 31 instead of 1
- clojure - 嵌套测试的功能版本是什么?
- angular - 离子 - 自动选择 Checkblx
- html - 垂直居中溢出图像