【问题标题】:Find sum of the gaps in array, assembly language查找数组中的间隙总和,汇编语言
【发布时间】:2015-06-18 01:59:12
【问题描述】:

我被这个问题困住了。我们应该在数组中找到间隙的总和。我已经编写了代码来查找数组的总和,但不知道如何找到间隙的总和。这就是我所拥有的。所以差距是2,3,4,1,总和应该是10。

.386
.model flat,stdcall
.stack 4096
ExitProcess proto,dwExitCode:dword

.data
    array DWORD 0,2,5,9,10  
.code
main proc
    mov edi,OFFSET array
    mov ecx,LENGTHOF array
    mov eax,0

L1:
    add eax,[edi]
    add edi,TYPE array
    loop L1

    invoke ExitProcess,0
main endp
end main

【问题讨论】:

  • 减去两个值会得到一个间隙。您的循环应该比项目数短一,因为间隙比项目数少一。
  • 刚看到你的回复,还在习惯这个网站。我不确定如何使循环更短。不会是 mov ecx, LENGTHOF array/1 之类的吗?
  • 间隙的总和只是最后一个元素减去第一个元素,除非您在谈论间隙的绝对值,在这种情况下,如果数字不是,则不是增加。
  • 在这种情况下,总和应该是 10,间隙是书上给出的 2,3,4,1。
  • 对。这与最后一个元素 10 减去第一个元素 0 相同。我的意思是计算间隙的总和,您只需从最后一个元素中减去第一个元素。那是因为空白的总和是(a1 - a0) + (a2 - a1) + ... + (aN - aN-1),中间的所有项都取消了,剩下aN - a0

标签: arrays assembly


【解决方案1】:

我对刷新我的程序集的愿望为零...但为了让您入门,以下是我将如何在 C 中执行此操作(称为高级 PDP-11 汇编程序 IIRC)

int array[5] = [0,2,5,9,10]
int sum = 0;
int length = 5;

for (i = 0; i < length - 1; i++)
{
   sum += (array[i+1]-array[i]);
}
//sum is now equal to 10, 2 + 3 + 4 + 1

【讨论】:

  • 那种帮助,我会继续努力的。抱歉格式不好,我还在学习这个网站的代码块
  • 请注意,从技术上讲,您可以将其粘贴在 c 程序中(使用主包装器)并执行 gcc -S(我认为,也许是 -s)以使其吐出汇编。我强烈反对直接使用它,因为如果你刚开始使用汇编,它可能使用的指令(尤其是高度优化的指令)可能会相当古怪
  • 是的,我刚开始组装。问题是我们的文本很糟糕,整个班级都讨厌这种布局,而且还有一些非常糟糕的例子。我正在为每一项任务而苦苦挣扎。我比较了 vb、java 和 c++ 和汇编的恶臭。我仍然没有让这个工作:/
  • 您将从位置array + 4*4 读取dword(这是基数加上dword 的大小(4)乘以元素索引,其中第一个索引为0)。然后减去您从位置array 读取的dword
  • 错误:你写的是array[0],而不是array[i]
【解决方案2】:

找出差距总和的漫长道路:

.386
.model flat,stdcall
.stack 4096
ExitProcess proto,dwExitCode:dword

.data
    array DWORD 0,2,5,9,10  
.code
main proc
    mov esi,OFFSET array
    mov ecx,LENGTHOF array
    mov ebx,0                ; Start sum at 0
    cld                      ; Clear the direction bit (look up the LODS instruction!)
    lodsd                    ; Get the first value to start
    mov edx, eax             ; Save "previous" element read in edx
    dec ecx                  ; Decrement the loop counter 'cuz we read one
L1:
    lodsd
    sub ebx, edx             ; sum = sum + (this element - prev element)
    add ebx, eax             ; or, sum = sum - prev, then sum = sum + this
    mov edx, eax             ; save previous element in edx
    loop L1

    mov eax, ebx             ; put the result in eax
    invoke ExitProcess,0
main endp
end main

如果您需要长时间执行此操作,但不允许使用 lodsd,那么我将其作为练习,将您的循环转换为不使用 lodsd

简单的方法是认识到差距的总和是:

(a[1] - a[0]) + (a[2] - a[1]) + ... + (a[N] - a[N-1])

假设您不采用差异的绝对值,那就是:a[N] - a[0]。可以按如下方式计算(注意:我不确定数组 + 偏移量的 MASM 语法,因此您可能需要稍作修改):

.386
.model flat,stdcall
.stack 4096
ExitProcess proto,dwExitCode:dword

.data
    array DWORD 0,2,5,9,10  
.code
main proc
    mov ebx, LENGTHOF array
    dec ebx                  ; last element is at length-1 index
    shl ebx, 2               ; length * 4 for size of DWORD
    mov eax, [array + ebx]   ; read last element
    sub eax, [array]         ; subtract first element

    invoke ExitProcess,0
main endp
end main

【讨论】:

  • 哇,谢谢。 tbh 我更喜欢第一个例子,但我检查了 lodsd 并没有在我们的课堂上讨论几个星期,所以我不知道它是否会被接受。它没有说绝对值,所以我认为这没关系。感谢您的所有帮助,以及 cmets 解释什么是做什么的。与 c++ 相比,汇编将花费我更多的时间来理解。
  • @megagig,我认为,如果必须,您可以将第一个示例转换为离散地址。查看lodsd 做了什么并模仿它。它所做的只是(1)将esi指向的内容移动到eax,然后(2)将esi增加eax字节的大小(即4)。这真的很简单。如果需要,Google 搜索“MASM 寻址模式”。
  • 我继续往前看我们的文字,以了解 losds 的作用。它基本上说它将 esi 中的任何内容加载到 eax 中,所以在我看来,我所要做的就是将 lodsd 更改为 mov eax, esi 但这不起作用;/
  • @megagig 它碰巧在没有第一个lodsd的情况下工作,因为数组中的第一个值是0,你可能已经在eax中有0 .但是正确的解决方案保留了第一个lodsd。请记住,如果一个程序碰巧工作,它不一定是正确的。 :) 理解的真正关键是尝试理解为什么每个步骤都存在。删除某些东西以查看它是否仍然有效可能非常具有欺骗性。
  • 第一个版本有一个比必要的循环携带的依赖链。 sum += a[i+1] / sum -= a[i] 修改 sum 两次,因此循环受到延迟的限制,每 2 次迭代运行一个周期。如果您将循环开销保持在足够低的水平,则执行 sum += (a[i+1] - a[i]) 可以在每 1 次迭代中运行一个循环器。不过,将“next”元素保存在寄存器中以用作下一次迭代的“prev”元素是很好的。
【解决方案3】:
Include Irvine32.inc

.data

array dword 0,2,5,7,9]              ; Array initializatiom

Sum dword 0                         ; variable containing sum

counter dword ?

.code

main proc

mov eax,0                         ; eax=0 because no garbage value is shown

mov esi,offset array              ; esi caontain array 1st index address
mov ecx,lengthof array-1          ; loop is repeated 4 times as two no are compared

  l1:

            add eax,[esi+4]                   ; eax have 2nd value of array
            sub eax,[esi]                     ; sub array 2nd and first value

            add esi,type array                ; Esi have next array value after each alteration 

            add sum,eax                       ; Sum is stored after each alteration

  loop l1

call writeint

    exit
main ENDP
END main

【讨论】:

  • 你测试过这个吗?两个元素之间的差距仅取决于这些元素,而不取决于差距的旧值,如果您阅读现有答案,您会注意到这一点。如果你认为你有一些有用的东西可以添加一个新的答案,你应该用代码之外的文本来解释你的代码的有趣之处。
  • 感谢您的专心我测试这段代码这段代码生成两个单独值之间所有差异的总和 af 数组例如,如果我们有一个数组 0,3,5 比第一个元素之间的差异是 3
  • 但是你add eax, [esi+4] 而不是mov eax, [esi+4]。因此,在第二次迭代中,您将在 0、3、5 示例中使用 sum += 5,而不是 sum += 2。这就是我所说的不依赖于差距的旧值的意思。
  • 再次感谢让我们重新考虑示例我们有 3 个数组元素 0 、 3 、 5 * 我使用 add eax,[ esi + 4 ] ,因为我使用 Dword 数组并且 esi 包含第一个数组值的引用* 所以对于下一个数组 val 的引用,我必须在第一个数组值引用中添加 4 * 所以添加 eax,[esi + 4] 将数组的第二个值 3 移动到 eax 寄存器 * 第二个命令 sub eax,[esi] 这个命令从 eax 寄存器中减去数组第一个索引上的 val 最后,我们将此值加到 sum 中,即 0
  • add eax, [esi+4] 不会移动第二个值,它会增加已经存在的值。它恰好在第一次迭代中为零。如果您使用mov eax, [esi+4] 而不是add,我认为您的代码是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-28
  • 2010-12-24
  • 2018-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多