我正在寻找使用纯汇编输出整数。我在64位Linux机器上使用nasm。目前我正在寻找一种输出整数来调试编译器的方法,但我想使用相同的代码来编写操作系统,这也是我不仅仅使用printf()
的原因。经过多次搜索和挫折,我想出了这段代码
SECTION .data
var: db " ",10,0
SECTION .text
global main
global _printc
global _printi
main:
mov rax, 90
push rax
call _printi
xor rbx, rbx
mov rax, 1
int 0x80
_printi:
pushf
push rax
push rbx
push rcx
push rdx
mov rax, [rsp+48]
mov rcx, 4
.start:
dec rcx
xor rdx, rdx
mov rbx, 10
div rbx
add rdx, 48
mov [var+rcx], dl
cmp rax, 0
jne .start
mov rax, [var]
push rax
call _printc
pop rax
pop rdx
pop rcx
pop rbx
pop rax
popf
ret
_printc:
push rax
push rbx
push rcx
push rdx
mov rax, [rsp+40]
mov [var], rax
mov rax, 4
mov rbx, 1
mov rcx, var
mov rdx, 4
int 0x80
pop rdx
pop rcx
pop rbx
pop rax
ret
请注意,在移植到OS开发时,我将使用BIOS调用替换0x80调用。
我的问题是如何进一步优化甚至美化这段代码。我的第一个想法是单独替换所有寄存器,但没有任何64位pusha
指令......
答案 0 :(得分:2)
以下是对例程的一些可能的更改:
_printi:
pushf
push rax
push rbx
push rcx
push rdx
mov rax, [rsp+48]
mov rcx, 4
mov rbx, 10 ; --moved outside the loop
.start:
dec rcx
xor rdx, rdx
div rbx
add rdx, 48
mov [var+rcx], dl
cmp rax, 0
jne .start
; mov rax, [var] -- not used
; push rax -- not used
call _printc
; pop rax -- not used
pop rdx
pop rcx
pop rbx
pop rax
popf
ret
我还注意到算法中的一些限制。如果该数字大于9999,则代码将继续将数字放在分配的空间之外,覆盖其他一些数据。该例程不是完全可重复使用的,即如果你打印123,那么它将是129。