在Assembly x86中获取最多三个数字时的分段错误

时间:2014-03-10 05:15:38

标签: c assembly

我试图使用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)
}

2 个答案:

答案 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, %ecxecxeax进行比较,而不是相反。所以代码

cmpl %eax, %ecx
jl firstsmaller
如果ecx小于eax

会跳转。