x86 NASM|仅在第一次和第三次循环中输入



我有一个循环成功运行了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 

换行符仍将存储在内存中,但您不会打印它,因为您将少循环一次。

相关内容

  • 没有找到相关文章

最新更新