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

Reversing a string and printing it in IA32 assembly

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

leal cadena, %eax
pushl %eax
leal leer, %eax
pushl %eax  
call scanf
addl , %esp

xorl %edx, %edx

对比:

movb cadena(%edx), %al
incl %edx
cmpb [=12=], %al
jne Contar

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

addl $-2, %edx

反转:

movb cadena(%edx), %al
pushl %eax
leal imp, %ebx
pushl %ebx
call printf
addl , %esp

decl %edx
cmpl [=13=], %edx
jge Invertir

movl , %eax
int [=13=]x80

我在编译时使用命令-nostartfiles。它有效,但是当我 运行 它时,输入 "Invertir" 时出现分段错误。我需要帮助来检测此代码中的错误。

谢谢!

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

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

如果你解决了这个问题,你将 运行 进入下一个问题,即你的 cmpjne 之间有一个 incl %edx,这将改变标志,这样您就不会在比较结果上分支,而是在增量上分支。解决方案:交换 cmpincl.

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

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

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

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