Вы можете использовать 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
ret
Не могли бы вы уточнить? Можно ли подсчитать ecx так, чтобы от 0 до w и как выполнять проверки, например, как y 0. Где это будет? поэтому у меня есть mov 12 (% ebp),% ecx .L14 # вышеперечислен. Он делает все это, а затем возвращается до ecx = 0? loop .L14 –
beginner
Нет, как я уже сказал, 'loop' отсчитывает до нуля. Вы не можете его подсчитать. – Jester
Обратите внимание, что вы можете использовать что-то вроде 'mov w,% edx' и' sub% ecx,% edx', чтобы увеличить счетчик от '0' до' w-1' в '% edx'. –