1

所以基本上我正在尝试读取一个字符串,增加一个计数器(在本例中为 %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

_开始:

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

简介:

movb cadena(%edx), %al
incl %edx
cmpb $0, %al
jne Contar

leal salidafinal, %ecx
pushl %ecx
call printf
addl $4, %esp

addl $-2, %edx

逆变器:

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”时会出现分段错误。我需要帮助来检测这段代码有什么问题。

谢谢!

4

1 回答 1

1

您的直接问题是cmpb '\n', %al缺少$at&t 语法中所需的符号以使其立即生效。事实上,它'\n'被认为是一个地址,并且是一个无效的地址。你应该使用cmpb $'\n', %al.

但是scanf根本不会'\n'放入您的缓冲区,因为%s停在空白处。所以你真的想寻找一个终止的零字节,那就是 use cmpb $0, %al。或者,如果您真的需要阅读整行,请fgets改用。

如果你解决了这个问题,你会遇到下一个问题,那就是你和incl %edx之间有一个会改变标志的,所以你不会在比较的结果上分支,而是在增量上。解决方案:交换和。cmpjnecmpincl

还有一个问题是一些寄存器,包括%edx,是调用者保存的。因此,它们可以被调用的函数修改,你可以这样做call printf。您应该push/pop围绕这两者来保持价值。

\n即使在所有这些之后,由于缓冲,您可能在手动打印最终结果之前不会看到任何输出。

请注意,如果你打算使用 C 库,你真的不应该使用-nostartfiles. 相反,您应该使用入口点main并正常组装和链接。此外,您应该简单地从main(或最多call exit)返回而不使用直接系统调用,因为这不允许 C 库正确清理。顺便说一句,这也会刷新 I/O 缓冲区,因此即使没有额外的换行符,您也会看到输出。

你真的应该学会使用调试器。

于 2015-06-01T00:15:55.823 回答