【问题标题】:Loop Assembly x86循环组件 x86
【发布时间】:2014-11-01 23:22:06
【问题描述】:

我是汇编(x86 ATT 语法)的初学者。我正在处理一项任务,我必须遍历二维数组的每个索引并找到 1 的数量。该方法采用 2d int array,int w, int h。如何实现循环从 0 到 w 并使用循环指令反弹。我知道如何使用 jmp 指令执行此操作,但循环只会给我错误/segFaults。这是我对跳转语句的尝试,它有效。我将如何使用循环指令转换内循环?

pushl   %ebp
movl    %esp, %ebp

movl    $0, -4(%ebp)
movl    $0, -8(%ebp)
movl    $0, -12(%ebp)
movl    $0, -4(%ebp) #outside loop
jmp .L10

.L14:  #Inner Loop
movl    $0, -8(%ebp)
jmp .L11

.L13:
movl    -4(%ebp), %eax
leal    0(,%eax,4), %edx
movl    8(%ebp), %eax
addl    %edx, %eax
movl    (%eax), %eax
movl    -8(%ebp), %edx
sall    $2, %edx
addl    %edx, %eax
movl    (%eax), %eax
cmpl    $1, %eax
jne .L12
addl    $1, -12(%ebp)

.L12:
addl    $1, -8(%ebp)
.L11: #check inner loop
movl    -8(%ebp), %eax
cmpl    12(%ebp), %eax
jl  .L13 
addl    $1, -4(%ebp)

.L10: #check outside loop
movl    -4(%ebp), %eax
cmpl    16(%ebp), %eax
jl  .L14
movl    -12(%ebp), %eax

leave
ret

【问题讨论】:

    标签: c arrays assembly x86 att


    【解决方案1】:

    通常使用loop 没有任何优势,只是代码可能更小。它通常速度较慢且灵活性较差,因此不推荐。

    也就是说,如果您仍然想使用它,您应该知道它使用ecx 寄存器来倒数到零。所以你需要重组你的代码来适应它。在您的情况下,这意味着使用 w 的值加载 ecx 并让它倒计时。您还需要在索引期间应用-1 的偏移量,因为您当前的循环变量从0 变为w-1,但ecx 将从w 变为1(含)。

    此外,loop 指令在循环体之后使用,即它实现了一个 do-while 循环。如果计数为零,要跳过循环体,可以使用伴随指令JECXZ

    【讨论】:

    • 您能详细说明一下吗?是否可以将 ecx so 0 计数到 w 以及如何执行检查,例如 if y0。那会去哪里?所以我上面有 mov 12(%ebp),%ecx .L14 #referenced。它完成了所有这些,然后返回直到 ecx=0?循环.L14
    • 不,正如我所说,loop 倒计时到零。你不能算数。
    【解决方案2】:

    您可以同时使用lodsl(默认上移 %esi)和loop(下移 %ecx)。我不确定它是否比 gcc 从 c 生成的更有效,c 基本上是你的代码,但它看起来更漂亮。

    我在这里所做的并没有准确地回答您的问题——我假设整个数组连续存储,而不是使用loop 作为内部循环,然后只需要担心一个循环。在我的机器上从 c 编译时,它是连续存储的,但我不确定你是否应该依赖它。希望我所做的能让您充分了解looplodsl 的工作原理,并且您可以修改代码以仅在内部循环中使用它们。

    .data
    x:
        .long 6
    y:
        .long 5
    array:
        .long 1,1,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1 
    
    .text
    .global _start
    _start:
        # set up for procedure call
        push x  
        push y
        push $array
        # call and cleanup
        call cnt
        add $0xc, %esp
        # put result in %ebx and finish up 
        #(echo $? gives value in bash if <256)  
        mov %eax, %ebx
        mov $1, %eax
        int $0x80
    
    # %ebx will hold the count of 1s
    # %ecx will hold the number of elements to check
    # %esi will hold the address of the first element
    # Assumes elements are stored contiguously in memory
    cnt:
        # do progogue
        enter $0, $1
        # set %ebx to 0
        xorl %ebx, %ebx
        # grab x and y parameters from stack and
        # multiply together to get the number of elements
        # in the array
        movl 0x10(%ebp), %eax   
        movl 0xc(%ebp), %ecx
        mul %ecx
        movl %eax, %ecx
        # get address of first element in array
        movl 0x8(%ebp), %esi 
    getel:
        # grab the value at the address in %esi and increment %esi
        # it is put in %eax
        lodsl
        # if the value in %eax is 1, increment %ebx
        cmpl $1, %eax
        jne ne
        incl %ebx
    ne:
        # decrement %ecx and if it is greater than 0, keep going
        loop getel
        # %ecx is zero so we are done.  Put the count in %eax
        movl %ebx, %eax
        # do epilogue
        leave
        ret
    

    没有所有的cmets真的更漂亮。

    .data
    x:
        .long 6
    y:
        .long 5
    array:
        .long 1,1,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1 
    
    .text
    .global _start
    _start:
        push x  
        push y
        push $array
        call cnt
        add $0xc, %esp
        mov %eax, %ebx
        mov $1, %eax
        int $0x80
    
    cnt:
        enter $0, $1
        xorl %ebx, %ebx
        movl 0x10(%ebp), %eax   
        movl 0xc(%ebp), %ecx
        mul %ecx
        movl %eax, %ecx
        movl 0x8(%ebp), %esi 
    getel:
        lodsl
        cmpl $1, %eax
        jne ne
        incl %ebx
    ne:
        loop getel
        movl %ebx, %eax
        leave
        ret
    

    【讨论】:

      猜你喜欢
      • 2020-04-30
      • 2018-09-02
      • 1970-01-01
      • 2023-03-03
      • 2011-12-08
      • 2013-07-25
      • 1970-01-01
      • 2017-01-23
      • 2012-03-05
      相关资源
      最近更新 更多