所以基本上我试图读取一个字符串,增加一个计数器(在这种情况下,%edx),直到我读到一个\ n,然后,向后反转打印它。
这是我的代码:
.section .data
cadsal:
.asciz "Por favor ingrese su cadena:\n"
leer:
.asciz "%s"
salidafinal:
.asciz "La cadena introducida, invertida es:\n"
imp:
.asciz "%c\n"
.section .bss .comm cadena,50,1
.section .text
.globl _start
_start:
leal cadsal, %eax
pushl %eax
call printf
addl $4, %esp
leal cadena, %eax
pushl %eax
leal leer, %eax
pushl %eax
call scanf
addl $8, %esp
xorl %edx, %edx
Contar:
movb cadena(%edx), %al
incl %edx
cmpb $0, %al
jne Contar
leal salidafinal, %ecx
pushl %ecx
call printf
addl $4, %esp
addl $-2, %edx
Invertir:
movb cadena(%edx), %al
pushl %eax
leal imp, %ebx
pushl %ebx
call printf
addl $8, %esp
decl %edx
cmpl $0, %edx
jge Invertir
movl $1, %eax
int $0x80
我在编译时使用命令-nostartfiles。它可以工作,但是当我运行它时,进入" Invertir"时会出现分段错误。我需要帮助来检测此代码中的错误。
谢谢!
答案 0 :(得分:1)
您的直接问题是cmpb '\n', %al
,它缺少at& t语法中所需的$
符号,以使其立即生效。实际上,'\n'
被视为地址,而无效地址被认为是地址。您应该使用cmpb $'\n', %al
。
但是scanf
根本不会将'\n'
放入缓冲区,因为%s
会在空格处停止。所以你真的想要寻找终止零字节,即使用cmpb $0, %al
。或者,如果您确实需要阅读整行,请改用fgets
。
如果您解决了这个问题,那么您将遇到下一个问题,即您incl %edx
和cmp
之间的jne
会改变标记,因此您不会分支比较的结果但增量。解决方案:交换cmp
和incl
。
另一个问题是某些寄存器(包括%edx
)被调用者保存。因此,它们可以通过被调用的函数进行修改,然后执行call printf
。您应该push
/ pop
围绕这两者保留价值。
即使在所有这些之后,由于缓冲,您可能无法在手动打印最终\n
之前看到任何输出。
请注意,如果您打算使用C库,则不应使用-nostartfiles
。相反,您应该使用入口点main
并正常汇编和链接。此外,您应该从main
(或最多call exit
)返回,而不是使用直接系统调用,因为这不允许C库正确清理。顺便说一下,这也会刷新I / O缓冲区,所以即使没有额外的换行符,你也可以看到输出。
你应该学会使用调试器。