程序集x86 Win32

时间:2016-10-20 02:52:55

标签: assembly x86 x86-64

我正在尝试使用x86架构学习Assembly。我可以做基本的计算,如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

1 个答案:

答案 0 :(得分:-1)

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

缺少

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

你没有定义什么是" string"也适合你。

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

              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指向的内容)对于' '等)。并通过指导参考指南面对,确保您了解每条指令的准确工作方式。

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

最后关于你的问题本身:

您的代码完全按照您编写的方式工作,即。与你原来的意图完全无关"将非空格字符发送到第二个字符串",代码甚至不接近它。

为什么你写了不相关的代码...很难说,可能你应该尝试将你原来的意图打破更简单的子任务(在英文评论中),并在你实现简单子时保留它们带有指令的步骤,因此您可以在调试期间将CPU中发生的事情与原始意图进行比较。

xchg交换两个值。当然,如果您了解字符串在内存中的存储方式,以及您希望与哪个其他值进行交换(取决于您的意图),那么即使是字符串操作也可以使用此类指令。

会有更有效的方式吗?

很难说,我甚至不确定你想要达到的目标。如果&#34;当前输出:____30&#34; (_是空格),&#34;想要输出:30&#34;,那么你实际上不需要修改字符串,你应该计算初始空格字符,然后给&# 34;输出&#34;子例程xStart + <space_count>地址,因此它不会遇到包含空格的字节。或者可能有dtoa的某些配置,或者您的库中的某些其他功能就像C printf一样,您可以在其中轻松指定确切的格式。

编辑:&#34;很难说&#34;强调:

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

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

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

其次,你陈述了那个指令所做的显而易见的事情。你应该归档你的人类意图&#34;在评论中,即:

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

如果你愿意这样做,就会更容易指出,与指示中的实施相比,你的人类意图消失了,并将你的心智错误指向你。

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