c - 这两条指令在以下函数中做了什么?
问题描述
所以我几乎是 IA32 汇编语言的菜鸟。我尝试将此 C 函数编译为 IA32 程序集(-mpreferred-stack-boundary=2
):
__attribute__((cdecl))
int odd_sum(int a[], int n, int sum) {
if (n == 0) return sum;
else if ((a[n-1] % 2) == 0)
return odd_sum(a, n-1, sum);
else return odd_sum(a, n-1, sum + a[n-1]);
}
和 GCC 输出这个:
.file "test.c"
.text
.globl _odd_sum
.def _odd_sum; .scl 2; .type 32; .endef
_odd_sum:
LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $12, %esp
cmpl $0, 12(%ebp)
jne L2
movl 16(%ebp), %eax
jmp L3
L2:
movl 12(%ebp), %eax
addl $1073741823, %eax
leal 0(,%eax,4), %edx
movl 8(%ebp), %eax
addl %edx, %eax
movl (%eax), %eax
andl $1, %eax
testl %eax, %eax
jne L4
movl 12(%ebp), %eax
leal -1(%eax), %edx
movl 16(%ebp), %eax
movl %eax, 8(%esp)
movl %edx, 4(%esp)
movl 8(%ebp), %eax
movl %eax, (%esp)
call _odd_sum
jmp L3
L4:
movl 12(%ebp), %eax
addl $1073741823, %eax
leal 0(,%eax,4), %edx
movl 8(%ebp), %eax
addl %edx, %eax
movl (%eax), %edx
movl 16(%ebp), %eax
addl %eax, %edx
movl 12(%ebp), %eax
subl $1, %eax
movl %edx, 8(%esp)
movl %eax, 4(%esp)
movl 8(%ebp), %eax
movl %eax, (%esp)
call _odd_sum
L3:
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE0:
.ident "GCC: (MinGW.org GCC-8.2.0-3) 8.2.0"
我无法理解的是这两行:
addl $1073741823, %eax
leal 0(,%eax,4), %edx
我知道这两行应该与 . 有关系a[n-1]
,但我似乎无法理解他们在这个过程中到底做了什么。有人可以帮我解决这个问题吗?
解决方案
这只是一种计算数组偏移量的奇特方式a[n-1]
。
1073741823
是0x3fffffff
。例如,如果n
是 3,它将添加它们并获取0x40000002
. 然后它乘以 4 与第二条指令,结果是0x00000008
,丢弃最高位。
所以我们留下了 8 个字节的偏移量,这正是您需要的偏移量(以字节为单位)a[n-1]
,即a[2]
(当 an 的大小int
为 4 个字节时)。
推荐阅读
- python - 如何从我的代码中修改 xpath 以检索所需的数据
- visual-studio - LLVM Visual Studio 集成失败
- angular - 没有 ngOnDestroy,角度取消订阅不起作用
- dart - 新手帮助:系统找不到指定的路径
- python - 在 python 2.7 中使用 modulefinder 来发现 pyd 文件中的依赖项
- r - 当字符串包含无法识别的转义时,R自定义错误消息
- python - 操作数据框,使列总和等于常数
- javascript - 基于同一表行中另一个值的单选按钮选择状态
- gtk3 - Vala GtkButton.Clicked.Connect 不调用函数
- python - 将日期时间数据转换为正确格式 arcpy python arcmap