我有一个循环成功运行了3次,但我在这个循环中的输入只在第一次运行。我是新组装的,所以请耐心等待。
代码:
section .bss
| d times 3 resb 1 ;array to store input
| i resb 1 ;counter
section .text
| global _start
|
| _start:
| | mov ecx, 3
| | mov [i], byte 0
| |
| | loop_here:
| | | push ecx
| | |
| | | mov eax, 3
| | | mov ebx, 0
| | | mov ecx, d
| | | add ecx, [i]
| | | inc byte [i]
| | | mov edx, 1
| | | int 80h
| | |
| | | pop ecx
| | loop loop_here
| |
| | mov eax, 1
| | xor ebx, ebx
| | int 80h
输出:
2 ;I inserted 2 as an input
2 ;I inserted 2 again as input
[Program finishes]
后来我想这个循环可能不会第三次运行了,所以我稍微修改了一下代码。
新代码:
section .bss
| d times 3 resb 1 ;array to store input
| i resb 1 ;counter
section .text
| global _start
|
| _start:
| | mov ecx, 3
| | mov [i], byte 0
| |
| | loop_here:
| | | push ecx
| | |
| | | mov eax, 4
| | | mov ebx, 1
| | | mov ecx, i
| | | add [ecx], byte 30h ;to actually print the count
| | | mov edx, 1
| | | int 80h
| | | sub [i], byte 30h ;to make again a counter
| | |
| | | mov eax, 3
| | | mov ebx, 0
| | | mov ecx, d
| | | add ecx, [i]
| | | inc byte [i]
| | | mov edx, 1
| | | int 80h
| | |
| | | pop ecx
| | loop loop_here
| |
| | mov eax, 1
| | xor ebx, ebx
| | int 80h
新输出:
02
122
[Program finishes]
解释:
0是计数器,2是我的输入。1和2是计数器,第二个2是我的第二个输入,这意味着循环成功运行,它只是在第二次运行时忽略输入代码
还有,我的代码中用于可视化作用域的直线是否使我的代码更可读?
Peter在评论中已经做了很好的工作,涵盖了大部分内容,但我想我会更详细地介绍:
x86loop
指令假定ecx
中有一个计数器。如果ecx
是而不是0,则loop
自动递减ecx
并跳到循环标签。由于您在循环中调用linux系统调用,并且linux希望缓冲区指针位于ecx
中,因此您可能应该使用不同的寄存器作为循环计数器,并使用某种跳转指令来执行此操作:
mov esi, 3 ; esi is your loop counter - loop 3 times
loop_here:
; do syscall
dec esi ; decrement loop counter
jnz loop_here ; jump to loop_here if esi is not zero
但是,在循环中调用系统调用的效率不是很高。相反,你可以这样做:
mov eax, 3 ; read
mov ebx, 0 ; fd for stdin
mov ecx, d ; address of d buffer into ecx
mov edx, 3 ; read 3 characters at most, the size of your buffer
int 80h
mov esi, eax ; read returns the number of bytes read in eax.
; we'll save it in esi
xor edi, edi ; edi will be our loop counter, this makes it 0
loop_here: ; first, we'll print the loop counter value
mov eax, 4 ; write
mov ebx, 1 ; fd for stdout
mov ecx, i ; address of i for write
mov edx, 1 ; write 1 byte
add edi, '0' ; convert edi loop counter to ASCII
mov [i], byte edi ; put lower byte of edi in i
int 80h
sub edi, '0' ; restore edi
mov eax, 4
mov ebx, 1
mov ecx, d ; address of d for write,
add ecx, edi ; plus current loop counter (offset)
mov edx, 1
int 80h
inc edi ; increment loop counter
cmp esi, edi ; compare to number of bytes read
jne loop_here ; jump to loop_here if not equal
这会调用read一次,但仍会在循环中调用write来写入计数器和d
的值。
要跳过输入中的尾随换行符,您可以在调用read之后尝试这样做(记住eax
具有读取的字节数(:
movzx edi, byte [d+eax-1] ; move and zero-extend last byte of d into edi
cmp edi, `n` ; is it a newline? (backticks required)
jne skip ; skip if not
dec eax ; otherwise, we'll print one less byte
skip:
; rest of your code here
换行符仍将存储在内存中,但您不会打印它,因为您将少循环一次。