我写了一个汇编代码来打印从1到9的数字,但是该代码只打印1且没有打印除1之外的其他任何元素并且仅接收到一个输出,这意味着该循环也没有运行。我无法弄清楚我的代码出了什么问题。

section .bss

        lena equ 1024
        outbuff resb lena

section .data

section .text

        global _start
        _start:
                nop
                mov cx,0

                incre:
                inc cx
                add cx,30h
                mov [outbuff],cx

                cmp cx,39h
                jg done

                cmp cx,39h
                jl print


                print:
                mov rax,1           ;sys_write
                mov rdi,1
                mov rsi,outbuff
                mov rdx,lena
                syscall
                jmp incre

                done:
                mov rax,60          ;sys_exit
                mov rdi,0
                syscall


我的操作系统是64位linux。此代码是使用nasm通过以下命令构建的:nasm -f elf64 -g -o num.o num.asm和ld -o num num.asm

最佳答案

经过一些实验后改写了答案。

您的代码中有两个错误,并且效率低下。

首先,在数字上添加0x30(将其从数字1转换为ASCII 1)。但是,您可以在循环内执行该增量。结果,您的第一次迭代cx为0x31,第二次为0x62(“ b”),第三次为0x93(无效的UTf-8序列)等。

只需将cx初始化为0x30,然后从循环内部删除添加即可。

但是还有另一个问题。在系统调用期间,RCX被破坏了。用cx替换r12会使程序正常工作。

除此之外,您将缓冲区的长度传递给write,但它只有一个字符。到目前为止的程序:

section .bss

        lena equ 1024
        outbuff resb lena

section .data

section .text

        global _start
        _start:
                nop
                mov r12,30h

                incre:
                inc r12
                mov [outbuff],r12

                cmp r12,39h
                jg done

                cmp r12,39h
                jl print


                print:
                mov rax,1           ;sys_write
                mov rdi,1
                mov rsi,outbuff
                mov rdx,1
                syscall
                jmp incre

                done:
                mov rax,60          ;sys_exit
                mov rdi,0
                syscall


除非现在,否则代码效率极低。您在相同条件下有两个比较,其中一个分支到下一条指令。

另外,如果将中断条件移到代码末尾,您的代码将更快,更小。同样,cx是一个16位寄存器。 r12是64位寄存器。我们实际上只需要8位。使用比需要的大的寄存器意味着我们所有的立即数都浪费了内存和缓存中的空间。因此,我们切换到r12的8位变体。经过这些更改,我们得到:

section .bss

        lena equ 1024
        outbuff resb lena

section .data

section .text

        global _start
        _start:
                nop
                mov r12b,30h

                incre:
                inc r12b
                mov [outbuff],r12b

                mov rax,1           ;sys_write
                mov rdi,1
                mov rsi,outbuff
                mov rdx,1
                syscall

                cmp r12b,39h
                jl incre

                mov rax,60          ;sys_exit
                mov rdi,0
                syscall


还有更多您可以做。例如,您调用write系统调用9次,而不是先填充缓冲区,然后再调用一次(尽管您已分配了1024个字节的缓冲区)。用零(xor r12, r12)初始化r12然后加0x30可能会更快。 (与寄存器的8位版本无关)。

关于linux - 打印nasm中的数字,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46511449/

10-09 21:08