2018-11-24

阶乘程序出现段错误

.section .data
        .section .text
        .globl _start
_start:
        pushl $8         #8入栈 sp=-4
        movl $1,%eax     #eax=1 
        call power       #调函数 sp=-8
        jmp exit
.type power, @function
power:
        pushl %ebp      #ebp入栈 sp=-12
        movl %esp,%ebp  #ebp=esp=-12
        subl $4,%esp    #esp-=4  =-16
        movl 8(%ebp),%ebx #ebx=8
        cmpl $1,%ebx      #if ebx==1
        je   power_end   #跳出
        subl 1,%ebx       #else : ebx-=1
        movl %ebx,-4(%ebp) #-16栈存入7
        call power         #调函数
        movl 12(%esp),%ecx
        addl %ecx,%eax
        addl $4,%esp
        popl %ebp
        ret

power_end:
        movl $1,%eax
        addl $4,%esp
        popl %ebp
        ret

exit:
        movl %eax,%ebx
        movl $1,%eax
        int $0x80

发现问题, subl 1,%ebx 中的1没有加$符号,加上后解决,得到36.
程序过于复杂,取代ecx为ebx后,加上注释为

.section .data
        .section .text
        .globl _start
_start:
        pushl $8         #8入栈 sp=-4
        movl $1,%eax     #eax=1 
        call power       #调函数 sp=-8
        jmp exit
.type power, @function
power:
        pushl %ebp      #ebp入栈 sp=-12
        movl %esp,%ebp  #ebp=esp=-12
        subl $4,%esp    #esp-=4  =-16
        movl 8(%ebp),%ebx #ebx=8
        cmpl $1,%ebx      #if ebx==1
        je   power_end   #跳出
        subl $1,%ebx       #else : ebx-=1
        movl %ebx,-4(%ebp) #-16栈存入7
        call power         #调函数
        movl 12(%esp),%ebx #从子函数跳出后,sp在dsp的-4位置,0(%esp)保存着子函数阶乘的数,12(%esp)是本阶
乘需要用的数。
        addl %ebx,%eax     #将本阶段数与递归回来的数相加
        addl $4,%esp       #esp归位
        popl %ebp          #弹出ebp
        ret                #跳出函数,返回值在eax中

power_end:
        movl $1,%eax
        addl $4,%esp
        popl %ebp
        ret

exit:
        movl %eax,%ebx
        movl $1,%eax
        int $0x80

迭代计算有误,应该是120,测试结果为14.
.section .data
.section .text
.globl _start
_start:
movl 5,%ecx
pushl %ecx
loop:
cmpl $1, %ecx
je exit
call power
jmp loop
.type power, @function
power:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%ecx
movl 12(%ebp),%eax
decl %ecx
movl %ecx,8(%ebp)
incl %eax
imull 12(%ebp),%eax
mov %eax,12(%ebp)

power_exit:
popl %ebp
ret
exit:
movl %eax,%ebx
addl 1,%eax
int $0x80
更改为如下,解决,设计上应该有一个自增的用于阶乘的参数,加上一个自减的用于计数的参数,再有一个记录前期所有阶乘结果的参数。三个参数都是迭代所需。
14那个结果原因在于上面代码计算出的结果是42*43,结果的二进制是0111 0000 1110 ,ebx带着这个值从程序中返回,但是返回的值需要小于255,也就是只收集一个字节,一个字节只有八个比特位,由于机器是小端的,所以上面的二进制在内存中是0110 0000 1110 按这个顺序读一个字节,恰好是0110 0000 ,cpu读这个内存得到的数其实是 0000 0110,也就是14,所以解决。

.section .data
        .section .text
        .globl _start
_start:
        movl $1,%edx
        pushl %edx
        movl $5,%ecx
        pushl %ecx
        movl $1,%eax
        pushl %eax
loop:
        cmpl $1, %ecx
        je exit
        call power
        jmp loop
.type power, @function
power:
        pushl %ebp
        movl %esp,%ebp
        movl 8(%ebp),%eax
        movl 12(%ebp),%ecx
        movl 16(%ebp),%edx
        decl %ecx
        movl %ecx,12(%ebp)
        incl %edx
        movl %edx,16(%ebp)
        imull %edx,%eax
        mov %eax,8(%ebp)

power_exit:
        popl %ebp
        ret
exit:
        movl %eax,%ebx
        addl $8,%esp
        movl $1,%eax
        int $0x80

你可能感兴趣的:(2018-11-24)