我写了一个汇编代码来打印从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/