我试图在64位汇编中编写一个函数(max),我不知道我做错了什么,也许你们中的一些人可以确定我做错了什么:/
这是功能:
int max(int a, int b) {
/* Return the larger of the two integers `a' and `b'. */
if (a > b)
return a;
else
return b;
}
这是我的汇编代码(带注释):
push %rbp
mov %rsp, %rbp
mov %rdi, %rax
mov %rsi, %rcx
test %rax, %rax // Checking if first parameter is signed
js .signedRAX
test %rcx, %rcx // Checking if second parameter is signed
js .signedRCX
jmp .compare // If either one signed then jump to .compare
.signedRAX:
test %rcx, %rcx // Checking if both are signed
js .signedRAXandRCX
mov %rcx, %rax // If not then return the positive number
jmp .end // finish the function
.signedRCX:
jmp .end // If only the second parameter is signed then jump
.signedRAXandRCX: // straight to end of function and return %rax
cmp %rax, %rcx // If both are signed compare which one is the max
jl .end
mov %rcx, %rax
jmp .end
.compare:
cmp %rax, %rcx // If both are positive then compare which one is
jg .end // the max
mov %rcx, %rax
.end:
mov %rbp, %rsp
pop %rbp
ret
在比较两个已签名且均为正数的参数时,输出错误。
答案 0 :(得分:2)
你的工作太复杂了。
如果我将您的计划输入gcc -S
,我会
max:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
movl 8(%ebp), %eax
cmpl 12(%ebp), %eax
jle .L2
movl 8(%ebp), %eax
jmp .L3
.L2:
movl 12(%ebp), %eax
.L3:
popl %ebp
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
如果我接管你的" ABI"以及传递参数的方式,
我得到了
max:
push %rbp
mov %rsp, %rbp
mov %rdi, %rax
mov %rsi, %rcx
cmpl %rcx, %rax
jle .L2
movl %rcx, %rax
.L2:
mov %rbp, %rsp
pop %rbp
ret
答案 1 :(得分:0)
这是来自问题的ASM的等效C伪代码。您可以看到,对于a >= 0
和b < 0
,它会返回b
。对于a < 0
和b >= 0
,它会返回a
。那是不对的。代码中可能存在其他错误,因为编码的操作非常简单。代码中很难看到任何内容。不要让简单的事情如此复杂。遵循KISS原则。
// test %rax, %rax
// js .signedRAX
if (a >= 0) {
// test %rcx, %rcx
// js .signedRCX
if (b >= 0) {
// .compare
// cmp %rax, %rcx // If both are positive then compare which one is
// jg .end // the max
if (a > b) {
b = a;
}
return b;
} else {
// .signedRCX
return b;
}
} else {
// .signedRAX
// test %rcx, %rcx // Checking if both are signed
// js .signedRAXandRCX
if (b >= 0) {
b = a;
return b;
} else {
// .signedRAXandRCX
// cmp %rax, %rcx // If both are signed compare which one is the max
// jl .end
if (a < b) {
b = a;
}
return b;
}
}