与rcx的nasm无限循环

时间:2017-03-27 15:10:23

标签: assembly nasm

我的代码以count作为输入来获取count个数字并存储在数组中

代码: 初始化消息

section .data
    msg db "Enter count"
    msgl equ $-msg
    msg1 db "Start Entering numbers"
    msg1l equ $-msg1

声明countarray以及宏以获取输入和输出

section .bss

count resb 1
arr resw 100;Maximum size 100 word
%macro general 4

    mov rax,%1
    mov rdi,%2
    mov rsi,%3
    mov rdx,%4
    syscall
%endmacro

主要功能

section .text

global _start

_start:
    general 1,1,msg,msgl  ;Enter a count display message
    general 0,0,count,1   ;Take count input
    general 1,1,count,1   ;Display that count
    sub byte[count],30h   ;Convert Ascii to number
    mov rcx,[count]       ;Store count to rcx
    general 1,1,msg1,msg1l   ;Display message
    mov rbx,arr            ;let rbx store starting address of arr
    again:

        general 0,0,rbx,2  ;Take number as input
        inc rbx            ;go to next address
        dec rcx            ;decrement counter
        jnz again          ;jump until counter is not zero
    ;general 1,1,msg,msgl
    general 60,0,0,0      ;Exit
  

输出

Enter count2
2Start Entering numbers3
1
1
1
1
2
3
3
3
3
3
3
3

Dosen&#t; t out of loop。 不知道为什么。

1 个答案:

答案 0 :(得分:1)

  1. mov rcx,[count] ;Store count to rcx

    这会从计数中加载 8 字节。但是,您只为计数(count resb 1)保留了一个。其余的来自下一个变量arr。如果有价值观,你会得到一个完全错误的rcx。将行更改为

    movzx rcx, byte [count]     ;Store count to rcx
    
  2. System V AMD64 ABI calling convention定义RCX作为来电者保存。这也适用于syscall。我建议改变宏:

    %macro general 4
        push rcx
        mov rax,%1
        mov rdi,%2
        mov rsi,%3
        mov rdx,%4
        syscall
        pop rcx
    %endmacro
    
  3. 系统调用SYS_READ(RAX = 0)导致您可能从scanf发出同样的问题。如果您没有读取所有字符,则输入缓冲区(STDIN)包含将由下一个SYS_READ读取的垃圾。如果只读取一个字符(general 0,0,count,1 ;Take count input),则STDIN以任何方式包含按下ENTER键的LF字符。您必须清空STDIN缓冲区。如果您不想管道输入,可以使用IOCTL函数:

    flush:                  ; http://stackoverflow.com/a/23040860/3512216
        push rcx
    
    ;    32 bit Linux
    ;    mov eax,54          ; kernel function SYS_IOCTL
    ;    mov ebx,0           ; EBX=0: STDIN
    ;    mov ecx,0x540B      ; ECX=0x540B: TCFLSH
    ;    xor edx, edx        ; EDX=0: TCIFLUSH
    ;    int 0x80            ; sys_call
    
        mov eax, 16         ; kernel function SYS_IOCTL
        xor edi, edi        ; RDI=0: STDIN
        mov esi, 0x540B     ; RSI=0x540B: TCFLSH
        xor edx, edx        ; RDX=0: TCIFLUSH
        syscall             ; sys_call
    
        pop rcx
        ret
    
  4. 这是纠正的整个群体:

    section .data
    
        msg db "Enter count "
        msgl equ $-msg
        msg1 db "Start Entering numbers",10
        msg1l equ $-msg1
        fmt: db `rax=%lu  rbx=%lu  rcx=%lu  rdx=%lu\n`,0
    
    section .bss
    
        count resb 1
        dummy resb 1
        arr resw 100;Maximum size 100 word
    
    %macro general 4
        push rcx
        mov rax,%1
        mov rdi,%2
        mov rsi,%3
        mov rdx,%4
        syscall
        pop rcx
    %endmacro
    
    section .text
    
    flush:  ; http://stackoverflow.com/a/23040860/3512216
        push rcx
    
    ;    32 bit Linux
    ;    mov eax,54          ; kernel function SYS_IOCTL
    ;    mov ebx,0           ; EBX=0: STDIN
    ;    mov ecx,0x540B      ; ECX=0x540B: TCFLSH
    ;    xor edx, edx        ; EDX=0: TCIFLUSH
    ;    int 0x80            ; sys_call
    
        mov eax, 16         ; kernel function SYS_IOCTL
        xor edi, edi        ; RDI=0: STDIN
        mov esi, 0x540B     ; RSI=0x540B: TCFLSH
        xor edx, edx        ; RDX=0: TCIFLUSH
        syscall             ; sys_call
    
        pop rcx
        ret
    
    global main
    main:
        general 1,1,msg,msgl    ; Enter a count display message
        general 0,0,count,1     ; Take count input
        call flush              ; flush STDIN
    
        general 1,1,count,1     ; Display that count
        sub byte[count],30h     ; Convert Ascii to number
        movzx rcx, byte [count] ; Store count to rcx
    
        general 1,1,msg1,msg1l  ; Display message
    
        mov rbx,arr             ; let rbx store starting address of arr
        again:
    
            general 0,0,rbx,2   ; Take number as input
            call flush
    
            inc rbx             ; go to next address
            dec rcx             ; decrement counter
            jnz again           ; jump until counter is not zero
        ;general 1,1,msg,msgl
        general 60,0,0,0        ; Exit