2015-05-31 117 views
1

所以基本上我试图读取字符串,增加一个计数器(在这种情况下,%edx),直到我读取一个\ n,然后向后打印它反转。反转字符串并将其打印在IA32程序集中

这是我的代码:

.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卡德纳,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

您的直接问题是cmpb '\n', %al,它缺少$需要的& t语法使其立即生效。实际上,'\n'被认为是一个地址,在那个地址是无效的。你应该使用cmpb $'\n', %al

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

如果解决这个问题,你会遇到哪些是你有你的cmpjne这将改变标志,所以你不会在比较,但增量的结果来分支之间的incl %edx下一个问题。解决方案:交换cmpincl

还有一个问题是一些寄存器,包括%edx,被保存起来。因此,他们可以通过调用函数进行修改,并且您可以做call printf。您应该围绕这两者保留价值push/pop

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

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

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

+0

嘿!谢谢回答。对不起,我仍然是一个业余爱好者。你到底意味着什么:你应该推动/弹出这两者以保持价值。我应该推什么? –

+0

''printf'事务(包括参数设置)''add%edx''和'add esp'后'pop%edx'。 – Jester

+0

交换第一个cmp和incl,“Contar”现在似乎工作正常。我现在在“Invertir”中出现分段错误。 修改后的addl $ -2,%edx因为contar完成,%edx从$ 0(字符串结尾)向前一步。 –