【问题标题】:Assembly x86 Win32汇编 x86 Win32
【发布时间】:2016-10-20 02:52:54
【问题描述】:

我正在尝试使用 x86 架构学习汇编。我可以进行基本计算,例如 add、sub、mul、imul、div 和 idiv。但是,当我尝试打印结果时,字符串中有几个空格。有没有办法删除这些额外的空间?我目前正在尝试通过遍历一个字符串并将非空格字符发送到第二个字符串来删除它们。如果这是这样做的方法,为什么我的代码不起作用?我在某处读过有关交换(xchg)的信息,但我不完全确定如何使用它。这会是一种更有效的方法吗?

              dtoa     product, eax      ; convert to ASCII characters
              dtoa     xStart, x
              dtoa     yContinue, y
              lea      edi, product
              mov      ecx, 20h          ; mov hex value of space into ecx

forStart:     cmp      [edi], ecx        ; compare edi to space
              jne      addToString
              add      edi, 4            ; get address of next array element
              cmp      [edi], 00h        ; cmp value of edi to null
              je       printResult
              jmp      forStart          ; loop through for next element

addToString:  mov      ecx, [edi]        ; mov value of edi into ecx
              add      edi, 4            ; get address of next array element
              cmp      [edi], 00h        ; cmp value of edi to null
              je       printResult
              jmp      forStart          ; loop through for next element

printResult:  output  resultLbl, xStart  ; output result

【问题讨论】:

    标签: assembly x86 x86-64


    【解决方案1】:

    这是相当不完整的。 dtoa 不是 x86 指令,所以很难说它做了什么(可能是一些十进制到字符串的转换例程,但如果没有它的源代码或适当的文档,它究竟产生了什么以及它是如何工作的都是谜)。

    product 声明丢失,也没有记录它是什么。

    你也没有为你定义什么是“字符串”。

    所有这些都很重要,因为在代码中你会这样做:

                  mov      ecx, 20h          ; mov hex value of space into ecx
    forStart:     cmp      [edi], ecx        ; compare edi to space
                  jne      addToString
    

    (顺便说一句,你可以将第一个写成mov ecx,' '

    cmp [edi],ecx 会将 DWORD 值与' ' 进行比较,那么您是否使用 UTF-32 编码的字符串?如果你使用经典的 ASCII 编码,那么你必须只比较 BYTE (cmp [edi],cl),并且只前进 1 (add edi,1)。

    cmp [edi], 00h -> 不清楚比较大小的值,使用一些大小说明符,如 NASM 中的 cmp [edi], BYTE 00h

    addToString 中,您获取了 4 个字节的字符串,但我看不到您“添加”它的位置,所以您在那里什么也不做。再次使用 4 字节元素对 UTF-32 编码有效,但不知何故我怀疑您使用的是 ASCII 以零结尾的字符串,所以您应该使用字节代替?

    如果您逐条执行指令,并了解寄存器中的值如何变化,并通过感兴趣地址的内存视图(edi 在扫描期间指向@ 987654333@等)。并通过指令参考指南来面对它,确保您了解每条指令的确切工作原理。

    所以这个问题表明缺乏努力(调试)+要求调试。

    最后是关于您的问题本身:

    您的代码确实按照您编写的方式运行,即。与您“将非空格字符发送到第二个字符串”的初衷完全无关,代码甚至都没有接近它。

    为什么你写了不相关的代码..很难说,也许你应该尝试将你的初衷更多地分解为更简单的子任务(英文为 cmets),并在你实现简单的子任务时保留它们带有说明的步骤,因此您可以在调试期间将 CPU 中发生的情况与您的原始意图进行比较。

    xchg 交换两个值。当然,如果您了解字符串是如何存储在内存中的,以及您想与其他值交换什么值(取决于您的意图),那么即使是字符串操作也可以使用这样的指令。

    会有更有效的方法吗?

    很难说,我什至不确定你想要实现什么。如果它像“当前输出:____30”(_ 是空格),“想要的输出:30”,那么您实际上不需要修改字符串,您只需计算初始空格字符,并给出“ output" 子程序xStart + <space_count> 地址,所以它不会遇到包含空格的字节。或者,dtoa 可能有一些配置,或者您的库中有一些其他功能,如 C printf,您可以在其中轻松指定精确的格式。


    编辑:“很难说”强调:

    而你保留在代码中的 cmets 通常是无用的,甚至是错误的。

    addToString:  mov      ecx, [edi]        ; mov value of edi into ecx
    

    首先,它不会将edi的值移动到ecx,而是将edi中的地址指向的内存内容的值,这是致命的区别。

    其次,您说的很明显,这就是该指令的作用。您应该在评论中归档您的“人类意图”,即:

    addToString:  mov      ecx, [edi]        ; reading 4 ASCII letters of string into ecx
    

    如果您这样做,就更容易指出与说明中的实施相比,您的人类意图在哪里发生了偏差,并将您的思想错误指出给您。

    事实上,可以只编写工作代码而不是你,但是你是否理解它为什么如此不同以及它是如何工作的......所以这需要你付出很多努力(理解它)真正帮助你。而且您在问题上表现出缺乏努力 - 没有必要提供工作示例。

    【讨论】:

      猜你喜欢
      • 2010-11-21
      • 1970-01-01
      • 2015-05-10
      • 2011-02-08
      • 2011-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多