问题描述
我正在为我的CIS班学习汇编,并且遇到了以下问题:
考虑以下x86-64代码:
loop:
movq %rsi,%rcx
movl $1,%eax
movl $0,%edx
.L2:
testq %rax,%rax
je .L4
movq %rax,%r8
andq %rdi,%r8
orq %r8,%rdx
salq %cl,%rax
jmp .L2
.L4:
movq %rdx,%rax
ret
上面的代码是通过编译具有以下总体形式的C代码(使用Arch gcc)生成的:
long loop(long a,long b) {
long result = 0;
for (long mask = ?; mask != ?; mask <<= ?) {
result |= (? & ?);
}
return result;
}
将上面的x86-64代码复制到C文件中作为注释。用x,y,结果和掩码注释x86-64代码的每一行。
好的,因此%rax
当然是返回值,我相信%rdi,%rsi,%rdx,%rcx
分别是a,b,result,mask
。但是令我困惑的是代码%r8
中这个假定的第五个参数。我是否误解了汇编语言中的所谓参数,还是汇编中的for循环有什么不同?任何反馈都非常感谢!
解决方法
好吧,在阅读了所有这些评论之后,我想我找到了答案。似乎是我误解了寄存器参数-认为它们必须与C代码中的变量连接。原来他们没有。因此,我搁置了C代码,只是坐下来分析了程序集,我认为我已经正确编写了每一步的内容(然后再写了等效的C代码)。如果有人可以,我希望对此有所确认。
装配功能:
%eax,%rax = RetVal
%rdi = Arg1 = a
%rsi = Arg2 = b
%edx,%rdx = Arg3 = result
%cl,%rcx = Arg4 = mask
%r8 = Arg5
loop:
movq %rsi,%rcx <=> Arg4 = Arg2
movl $1,%eax <=> RetVal = 1
movl $0,%edx <=> Arg3 = 0
.L2:
testq %rax,%rax <=> if RetVal == 0
je .L4 <=> go to .L4
movq %rax,%r8 <=> Arg5 = RetVal
andq %rdi,%r8 <=> Arg5 = (Arg5 & Arg1)
orq %r8,%rdx <=> Arg3 = (Arg3 | Arg5)
salq %cl,%rax <=> RetVal = (RetVal << Arg4)
jmp .L2 <=> go to .L2
.L4:
movq %rdx,%rax <=> RetVal = Arg3
ret <=> return RetVal
等效的C代码(?):
long loop(long a,long b) {
long result = 0;
for (long mask = b; mask != 0; mask <<= 1) {
result |= (mask & a);
}
return result;
}