我试图使用C来调用程序集32位AT&中的方法来获取最多三个数字。 T.当程序运行时,我得到一个分段错误(核心转储)错误,无法弄清楚原因。我的输入是正/负数和1,2,3的混合,两者都有相同的错误。
装配
# %eax - first parameter
# %ecx - second parameter
# %edx - third parameter
.code32
.file "maxofthree.S"
.text
.global maxofthree
.type maxofthree @function
maxofthree:
pushl %ebp # old ebp
movl %esp, %ebp # skip over
movl 8(%ebp), %eax # grab first value
movl 12(%ebp), %ecx # grab second value
movl 16(%ebp), %edx # grab third value
#test for first
cmpl %ecx, %eax # compare first and second
jl firstsmaller # first smaller than second, exit if
cmpl %edx, %eax # compare first and third
jl firstsmaller # first smaller than third, exit if
leave # reset the stack pointer and pop the old base pointer
ret # return since first > second and first > third
firstsmaller: # first smaller than second or third, resume comparisons
#test for second and third against each other
cmpl %edx, %ecx # compare second and third
jg secondgreatest # second is greatest, so jump to end
movl %eax, %edx # third is greatest, move third to eax
leave # reset the stack pointer and pop the old base pointer
ret # return third
secondgreatest: # second > third
movl %ecx, %eax #move second to eax
leave # reset the stack pointer and pop the old base pointer
ret # return second
C代码
#include <stdio.h>
#include <inttypes.h>
long int maxofthree(long int, long int, long int);
int main(int argc, char *argv[]) {
if (argc != 4) {
printf("Missing command line arguments. Instructions to"
" execute this program:- .\a.out <num1> <num2> <num3>");
return 0;
}
long int x = atoi(argv[1]);
long int y = atoi(argv[2]);
long int z = atoi(argv[3]);
printf("%ld\n", maxofthree(x, y, z)); // TODO change back to (x, y, z)
}
答案 0 :(得分:2)
代码导致分段错误,因为它在执行ret
指令时尝试跳回到无效的返回地址。这适用于所有三种不同的ret
指令。
之所以发生这种情况,是因为在返回之前没有弹出旧的基指针。对代码进行少量更改将消除故障。将每个ret
指令更改为:
leave
ret
leave
指令将执行以下操作:
movl %ebp, %esp
popl %ebp
将重置堆栈指针并弹出您保存的旧基指针。
此外,您的比较并未执行评论中指定的操作。当你这样做时:
cmp %eax, %edx
jl firstsmaller
%edx
小于%eax
时会发生跳转。所以你想要代码
cmpl %edx, %eax
jl firstsmaller
会在%eax
小于%edx
时跳转,如评论中所指定。
有关AT&amp; T / GAS语法中cmp
指令的详细信息,请参阅此this page。
答案 1 :(得分:1)
在从函数返回之前忘记弹出ebp
。
另外,cmpl %eax, %ecx
将ecx
与eax
进行比较,而不是相反。所以代码
cmpl %eax, %ecx
jl firstsmaller
如果ecx
小于eax
,会跳转。