我是汇编(x86 ATT语法)的初学者。我正在做一个赋值,我必须遍历二维数组的每个索引,并找到1的个数。这个方法接受二维整数数组,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发布于 2014-11-02 07:34:51
一般来说,使用loop没有任何优势,除了可能更小的代码。它通常速度较慢,灵活性较差,因此不推荐使用。
也就是说,如果您仍然想使用它,您应该知道它使用ecx寄存器进行倒数到零。因此,您需要重新构造代码以适应这种情况。在您的例子中,这意味着用w的值加载ecx并让它倒计时。在索引期间,您还需要应用-1的偏移量,因为当前的循环变量从0到w-1,而ecx将从w向下到1 (包括)。
此外,loop指令在循环体之后使用,也就是说,它实现了一个do-while循环。若要在计数为零时跳过循环体,可以使用配套指令JECXZ。
发布于 2014-11-02 17:35:50
您可以同时使用lodsl (默认情况下向上移动%esi )和loop (向下移动%ecx )。我不确定它是否比gcc从c生成的代码效率更高,但它看起来更漂亮。
我在这里所做的并没有准确地回答您的问题--而不是将loop用于内部循环,我假设整个数组都是连续存储的,然后只需要担心一个循环。在我的机器上从c编译时,它是连续存储的,但我不确定您是否应该依赖它。希望我所做的工作足以让您理解loop和lodsl是如何工作的,并且您可以修改代码,以便只在内部循环中使用它们。
.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没有所有的评论,它真的更漂亮。
.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
rethttps://stackoverflow.com/questions/26694319
复制相似问题