汇编语言中的分段错误

use*_*688 5 linux x86 assembly

我正在学习AT&T x86汇编语言.我正在尝试编写一个取整数n的汇编程序,然后返回结果(n/2 + n/3 + n/4).这是我做的:

.text
.global _start
_start:
    pushl $24
    call profit
    movl %eax, %ebx
    movl $1, %eax
    int $0x80

profit:
    popl %ebx
    popl %eax
    mov $0, %esi
    movl $4, %ebp
    div %ebp
    addl %eax, %esi
    movl %ecx, %eax
    movl $3, %ebp
    div %ebp
    addl %eax, %esi
    movl %ecx, %eax
    movl $2, %ebp
    div %ebp
    addl %eax, %esi
    movl %esi, %eax
    cmpl %ecx, %esi
    jg end
    pushl %ebx
    ret

end:
    mov %ecx, %eax
    ret
Run Code Online (Sandbox Code Playgroud)

问题是我得到了分段错误.问题出在哪儿?

nrz*_*nrz 8

我认为代码在这里失败了:

_start:
    pushl $24
    call profit
    movl %eax, %ebx
    movl $1, %eax
    int $0x80

profit:
    popl %ebx
    popl %eax
Run Code Online (Sandbox Code Playgroud)

所以,你push $24(4个字节)然后call profit,推送eip和跳转到profit.然后你弹出的值eipebx和值$24进入eax.

然后,最后,如果jg end分支到end:,那么堆栈将不会保存有效的返回地址并且ret将失败.你可能也需要pushl %ebx那里.

    cmpl %ecx, %esi
    jg end
    pushl %ebx
    ret

end:
    mov %ecx, %eax
    ; `pushl %ebx` is needed here!
    ret
Run Code Online (Sandbox Code Playgroud)

  • 解释中的细节水平很高.不错. (2认同)