课程
1896 字
约 6 分钟
大二上
GPT
计算机系统基础exercises/Homework/RainClass/chapter03·更新于 2026-09-15
int refunc (unsigned x) {
if( ___ )
return ___ ;
unsigned nx = ___ ;
int rv = refunc(nx) ;
return ___ ;
}
1 movl 8(%ebp), %ebx
2 movl $0, %eax
3 testl %ebx, %ebx
4 je .L2
5 movl %ebx, %eax
6 shrl $1, %eax
7 movl %eax, %(esp)
8 call refunc
9 movl %ebx, %edx
10 andl $1, %edx
11 leal (%edx,%eax), %eax
12 .L2 :
...
ret
GPT
填写完整的 C 代码:
int refunc(unsigned x) {
if (x == 0)
return 0;
unsigned nx = x >> 1;
int rv = refunc(nx);
return (x & 1) + rv;
}
汇编代码分析与对应 C 代码的还原:
-
函数参数读取:
1 movl 8(%ebp), %ebx- 将函数的第一个参数
x存入%ebx。 - C 对应:
unsigned x。
- 将函数的第一个参数
-
初始化返回值:
2 movl $0, %eax- 初始化
%eax为 0,对应if (x == 0) return 0;的返回值。
- 初始化
-
判断条件:
3 testl %ebx, %ebx 4 je .L2- 检查
%ebx是否为 0。如果是 0,则跳转到.L2并直接返回。 - C 对应:
if (x == 0) return 0;。
- 检查
-
计算 nx:
5 movl %ebx, %eax 6 shrl $1, %eax- 将
%ebx(x 的值)右移 1 位,将结果存入%eax。 - C 对应:
unsigned nx = x >> 1;。
- 将
-
递归调用:
7 movl %eax, %(esp) 8 call refunc- 将
%eax的值(nx)压入栈并调用函数refunc。 - C 对应:
int rv = refunc(nx);。
- 将
-
计算返回值:
9 movl %ebx, %edx 10 andl $1, %edx 11 leal (%edx,%eax), %eax- 第 9 行:将
%ebx的值复制到%edx。 - 第 10 行:计算
x & 1并存入%edx。 - 第 11 行:计算
(%edx + %eax),将结果存入%eax。 - C 对应:
return (x & 1) + rv;。
- 第 9 行:将
函数的功能:
-
功能描述:此函数计算一个非负整数
x的二进制表示中有多少个1(即汉明重量,Hamming Weight)。 -
递归过程
:
- 如果
x == 0,直接返回 0。 - 对
x的二进制表示右移 1 位,递归调用refunc计算其低位的 1 的个数。 - 最后将当前最低位的 1 与递归结果相加返回。
- 如果
示例运行:
-
输入:
refunc(5)(5 的二进制为101)refunc(5)→(5 & 1) + refunc(2)refunc(2)→(2 & 1) + refunc(1)refunc(1)→(1 & 1) + refunc(0)refunc(0)→0- 结果:
(1) + (0) + (1) + (0) = 2
-
输出:
2(5的二进制表示有 2 个1)。
Copilot
根据汇编代码,可以推断出C代码中缺失的部分,并说明函数的功能。
填写缺失的C代码
int refunc (unsigned x) {
if (x == 0)
return 0;
unsigned nx = x >> 1;
int rv = refunc(nx);
return (x & 1) + rv;
}
说明函数的功能
函数 refunc 的功能是计算输入的无符号整数 x 的二进制表示中1的个数。也就是计算 x 的二进制表示中有多少个1。
对应的汇编代码解释
movl 8(%ebp), %ebx:将参数x的值加载到寄存器ebx中。movl $0, %eax:将寄存器eax置为0。testl %ebx, %ebx:测试ebx是否为0。je .L2:如果ebx为0,跳转到标签.L2,返回0。movl %ebx, %eax:将ebx的值复制到eax中。shrl $1, %eax:将eax的值右移1位(相当于x >> 1)。movl %eax, (%esp):将eax的值压入栈中,作为递归调用refunc的参数。call refunc:递归调用refunc。movl %ebx, %edx:将ebx的值复制到edx中。andl $1, %edx:将edx与1进行按位与操作,得到x的最低位(即x & 1)。leal (%edx,%eax), %eax:将edx和eax的值相加,结果存入eax中。.L2:返回eax的值。
通过这些汇编指令,可以看出函数 refunc 通过递归计算 x 的二进制表示中1的个数。













