【问题标题】:Segmentation fault when querying for integers in Assembly在 Assembly 中查询整数时出现分段错误
【发布时间】:2014-02-22 01:35:21
【问题描述】:

所以我正在学习 intel x86 汇编,我正在尝试向用户查询两个整数,同时拒绝他们输入小于 0 的整数。虽然我一直遇到分段错误,但不知道为什么。

;.........................................................
;.........................................................
; sub-program to read an integer 
segment .Data
readmsg db "Enter two positive integers:", 0
negative_msg db "No, enter a POSITIVE integer.", 0
segment .text

int_cin:

push   ebp
mov    ebp,esp

mov    ecx, 2
mov    eax, readmsg
call   print_string

start:       
call   read_int
mov ebx, eax
cmp ebx, 0
jge skip
mov eax, negative_msg
call print_string
call print_nl
loop start
skip:
push ebx
dec ecx
loop start

pop  ebx
mov [Sec_Int], ebx
pop ebx
mov [First_Int], ebx

pop    ebp
ret

【问题讨论】:

    标签: assembly segmentation-fault


    【解决方案1】:

    我不确定您使用的是哪种 API,它提供了 print_stringprint_nlread_int,但我几乎可以肯定您不能期望 ECX 寄存器的值在那些调用(我记得的调用约定都没有保证)。因此,您的第一个错误是您希望 ECX 仅由您自己的代码更改,而不是由那些外部函数更改。

    如果我是对的并且 ECX 发生了意外变化,那么 loop 指令很有可能在等待 ECX 变为零时永远不会停止跳转到相应的标签。这会给你一个无限循环。

    进一步看,您会看到在该循环内,您在每次迭代时将 EBX 推入堆栈。如果循环无限,堆栈肯定会溢出,导致分段错误。

    附:如果第一个 loop start 因为 ECX 变为零而没有转到 start,则执行流程将继续执行以下指令,这会将 EBX 推入堆栈,再次减少 ECX(所以它现在是 -1),然后循环回到开始。下一次 ECX 会变为零(在理想条件下),真的不会那么快。

    附言您似乎混淆了标签地址和存储在这些地址中的值,这可能是导致分段错误的另一个原因。看看你如何首先将[readmsg] 传递给print_string,然后再将readmsg 传递给相同的函数。看起来很可疑。

    【讨论】:

    • 好的,你说得对,我修复了分段错误,现在循环就像你说的那样是无限的。我认为 ecx 可能不会仅仅因为我告诉它而完全覆盖它应该做的事情。计划是让它不断循环,直到它得到两个正整数,然后将它们从堆栈中弹出到 main .bss 中设置的两个变量中
    • 如果这些外部函数确实改变了 ECX,请考虑在进行外部调用之前保存寄存器值并在之后恢复它,或者使用内存中的变量来跟踪您的迭代。
    • 另外,您不应该在出错时减少 ECX(或内存中的计数器),您目前使用 loop 指令隐式执行此操作。
    猜你喜欢
    • 1970-01-01
    • 2018-09-03
    • 1970-01-01
    • 1970-01-01
    • 2016-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多