循环分段错误
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 &something
打印。注意&
获取地址,而不是内容。 .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_Codermov $S, %rdx
与mov $S,%edx
做同样的事情,但会消耗额外的存储空间。如果将某些内容加载到 32 位寄存器中,则寄存器的高 32 位会自动归零。在第 28 行,length
占用 1 个字节的存储空间,但您的 cmp
尝试读取 8 个字节。你认为会发生什么?以上是关于循环分段错误的主要内容,如果未能解决你的问题,请参考以下文章