循环分段错误

Posted

技术标签:

【中文标题】循环分段错误【英文标题】:Loop Segmentation Fault 【发布时间】:2016-06-24 06:32:52 【问题描述】:

这是我目前的代码。

            .data
S:          .string "-149"
Length:     .byte   -1
Result:     .quad 

            .text
            .globl main

main: 
    mov     S,%rdx              #Storage of string, counter, position and result in memory
    mov     Length, %rcx
    mov     Result, %rax
    mov     $10, %r10
    mov     $30, %r13
    mov     $-1, %r9

Loop1:                          #loop string from beginning to end  
    cmp     $0,0(%rdx)          #compare base addresss value with null
    je      Counter_Made        #if null, branch to end loop. 
    add     %r14, Length        #increment length by for each digit thats not null (creates counter for 2nd loop)
    add     $1, %rdx            #increment base by 1 to move onto next digit in string
    jmp     Loop1               #reinitiate loop


Counter_Made: 
    cmp     %r15,Length         #check if length is zero
    je      Output              #End program, output null result
    cmp     %r15,Length(%rdx)   #Determine negativity/positivity of integer
    jl      Negative_counter
    jmp     Positive_loop 

Positive_loop: 
    cmp     %r9,Length          #End of loop check 
    je      Output              #Store result if loop end condition satisfied
    mov     %r10, Length(%rdx)  #Store byte of integer in supplementary register
    sub     %r13,  %r10         #Conversion from 8bitASCII to 2Bit Binary
    imul    %r11, %r10          #Place holder multiplication 
    add     %r10, %rax          #Store cumulative addition in memory
    sub     %r14, Length        #Length decrement 
    jmp     Positive_loop       #reloop

Negative_counter:
    sub     %r14,Length
    jmp     Negative_loop

Negative_loop: 
    cmp     %r9,Length
    je      Negative_Complement 
    mov     %r10, Length(%rdx)  #Store byte of integer in supplementary register
    sub     %r13, %r10          #Conversion from 8bitASCII to 2Bit Binary
    imul    %r10, %r10          #Place holder multiplication 
    add     0(%rdx), %rax       #Store cumulative addition in memory
    sub     %r14, Length
    jmp     Negative_loop

Negative_Complement:
    not     %rdx                #Convert to 2's complement with negation and then + 1
    add     %r14,%rdx
    jmp     Output

Output:
    mov      %rdx, Result 
    ret 
#size mismatch for imul 
#Specific place in memory to put output or no?

该代码应该将表示任何有符号整数的字符串转换为其 2 的补码值。

我在一个循环中收到分段错误,我在这里尝试了多种不同的方法,但无济于事 - 谁能解释我应该如何修复此分段错误?我难住了。

这是 GDB 错误

Program received signal SIGSEGV, Segmentation fault.
Loop1 () at data.s:18
18      cmp     $0,0(%rdx)          #compare base addresss value with null

这是第二个错误。

Counter_Made () at data.s:28
28      cmp     $0,Length(%rdx)     #Determine negativity/positivity of integer, if <0 value is negative

我怀疑它是我试图用来解释循环的 Length(%rdx) 方法。会不会更好sub $1,%rdx

【问题讨论】:

要自己用 gdb 解决这个问题,你应该总是打印出出错的地址。由于寻址模式是(%rdx),所以运行p /x $rdx。您会看到可疑的 ASCII 范围内的十六进制数字。例如0x000000FF??????,在哪里?? bytes 是-149 ASCII 编码的十六进制值。这将是一个很大的线索,您在%rdx 中没有地址,尤其是在打印S 并看到它的地址是0x4... 或其他东西之后(Linux 上的数据部分地址在低 2G 的地址中空间,因此符号扩展的 32 位位移可以解决它们。) 我在第 10 行设置了一个中断来打印 S 但 GDB 说 $1 = Value can't be converted to integer. 因为它是一个字符串,这是有道理的。将 S 放入 %rdx 给了我(gdb) p /x $rdx $3 = 0x601038 这对我的价值来说没有意义。这是怎么回事? 第 10 行是mov S,%rdx。如果你在那里休息,%rdx 还没有被写入。我刚刚检查了一个简单的示例:我的测试用例中的 .data 部分地址是0x600464,由p /x &amp;something 打印。注意&amp; 获取地址,而不是内容。 .rodata 部分地址恰好是0x400424(链接后只读数据进入.text 部分)。所以0x601038 对我来说就像一个普通的数据段地址。如果您的代码仍然存在错误(mov S, %rdx 而不是 mov $S, %rdx),您会在 %rdx 中看到完全不同的东西。 【参考方案1】:

你想要

mov $S,%edx

将字符串的地址加载到%rdx。这是因为程序映像总是加载到地址空间的较低 4 GB 中。或者,您可以使用 %rip 相对 lea 来加载地址,即使进程映像加载到前 4 GB 之外:

lea S(%rip),%rdx

但该指令的编码稍长(两个额外字节)。

说明

mov S,%rdx

S指向的内存的前八个字节加载到%rdx中,这不是你想要的。

【讨论】:

我试图让所有的东西都保持与我得到的 imul 大小不匹配的代码相同的大小。 mov $S, %rdx 这样就够了吗? 类似地,第 28 行也给了我一个段错误。 @Egyptian_Coder mov $S, %rdxmov $S,%edx 做同样的事情,但会消耗额外的存储空间。如果将某些内容加载到 32 位寄存器中,则寄存器的高 32 位会自动归零。在第 28 行,length 占用 1 个字节的存储空间,但您的 cmp 尝试读取 8 个字节。你认为会发生什么?

以上是关于循环分段错误的主要内容,如果未能解决你的问题,请参考以下文章

多线程分段错误(for循环)

无法进入while循环:“分段错误”

循环C ++中的分段错误Openmp

在 C++ 中比较来自向量的字符串时出现分段错误

这段代码一次执行良好,另一次出现分段错误

为啥这段代码在 leetcode 运行良好,但在 geeksforgeeks 出现分段错误?