反转字符串并在 IA32 程序集中打印
Posted
技术标签:
【中文标题】反转字符串并在 IA32 程序集中打印【英文标题】:Reversing a string and printing it in IA32 assembly 【发布时间】:2015-05-31 23:03:55 【问题描述】:所以基本上我是在尝试读取一个字符串,增加一个计数器(在本例中为 %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”时会出现分段错误。我需要帮助来检测这段代码有什么问题。
谢谢!
【问题讨论】:
【参考方案1】:您的直接问题是 cmpb '\n', %al
,它缺少 at&t 语法中所需的 $
符号以使其立即生效。事实上,'\n'
被认为是一个地址,并且是一个无效的地址。你应该使用cmpb $'\n', %al
。
但是scanf
根本不会将'\n'
放入缓冲区,因为%s
会在空白处停止。所以你真的想寻找一个终止的零字节,那就是使用cmpb $0, %al
。或者,如果您确实需要阅读整行,请改用fgets
。
如果您解决了这个问题,您将遇到下一个问题,即您在 cmp
和 jne
之间有一个 incl %edx
,这将更改标志,因此您将不会根据比较不过是增量。解决方法:交换cmp
和incl
。
还有一个问题是一些寄存器,包括%edx
,是调用者保存的。因此,它们可以通过调用函数进行修改,您可以使用call printf
。你应该 push
/pop
围绕这两者来保留价值。
即便如此,在您手动打印最终的\n
之前,由于缓冲,您可能不会看到任何输出。
注意,如果你打算使用 C 库,你真的不应该使用-nostartfiles
。相反,您应该使用入口点main
并正常组装和链接。此外,您应该简单地从main
(或最多call exit
)返回而不使用直接系统调用,因为这不允许C 库正确清理。顺便说一句,这也会刷新 I/O 缓冲区,因此即使没有额外的换行符,您也会看到输出。
你真的应该学会使用调试器。
【讨论】:
嘿!谢谢回答。对不起,我仍然是组装的业余爱好者。你到底是什么意思:你应该推动/弹出这两个以保持价值。我应该推什么?push %edx
在printf
业务之前(包括参数设置)和pop %edx
在add esp
之后。
交换了第一个 cmp 和 incl,“Contar”现在似乎工作正常。我现在在“Invertir”中遇到分段错误。修改 addl $-2 , %edx 因为 contar 结束时 %edx 从 $0 (字符串结尾)向前迈进了一步。
没关系。学习了一点如何使用调试器。更改了我的代码中的一些内容。那个 pushl/pop 的东西救了我的命。非常感谢。以上是关于反转字符串并在 IA32 程序集中打印的主要内容,如果未能解决你的问题,请参考以下文章