反转字符串并在IA32程序集中打印它

时间:2015-05-31 23:03:56

标签: string assembly x86 att reversing

所以基本上我试图读取一个字符串,增加一个计数器(在这种情况下,%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"时会出现分段错误。我需要帮助来检测此代码中的错误。

谢谢!

1 个答案:

答案 0 :(得分:1)

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

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

如果您解决了这个问题,那么您将遇到下一个问题,即您incl %edxcmp之间的jne会改变标记,因此您不会分支比较的结果但增量。解决方案:交换cmpincl

另一个问题是某些寄存器(包括%edx)被调用者保存。因此,它们可以通过被调用的函数进行修改,然后执行call printf。您应该push / pop围绕这两者保留价值。

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

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

你应该学会使用调试器。