打印Int(或Int到String)

Win*_*pad 3 string int assembly nasm

我正在寻找一种方式来打印汇编(我使用的编译器是NASM在Linux上)的整数,但是,做了一些研究之后,我一直没能找到一个真正可行的解决方案.我能够找到一个基本算法的描述来实现这个目的,并在此基础上我开发了这个代码:

global _start

section .bss
digit: resb 16
count: resb 16
i: resb 16

section .data

section .text

_start:
mov             dword[i], 108eh         ; i = 4238
mov             dword[count], 1
L01:
mov             eax, dword[i]
cdq
mov             ecx, 0Ah
div             ecx  
mov             dword[digit], edx

add             dword[digit], 30h       ; add 48 to digit to make it an ASCII char
call            write_digit

inc             dword[count]

mov             eax, dword[i]
cdq
mov             ecx, 0Ah
div             ecx  
mov             dword[i], eax 
cmp             dword[i], 0Ah  
jg              L01

add             dword[i], 48            ; add 48 to i to make it an ASCII char
mov             eax, 4                  ; system call #4 = sys_write
mov             ebx, 1                  ; file descriptor 1 = stdout
mov             ecx, i                  ; store *address* of i into ecx
mov             edx, 16                 ; byte size of 16
int             80h

jmp             exit

exit:
mov             eax, 01h                ; exit()
xor             ebx, ebx                ; errno
int             80h

write_digit:
mov             eax, 4                  ; system call #4 = sys_write
mov             ebx, 1                  ; file descriptor 1 = stdout
mov             ecx, digit              ; store *address* of digit into ecx
mov             edx, 16                 ; byte size of 16
int             80h
ret
Run Code Online (Sandbox Code Playgroud)

我希望实现的C#版本(为清晰起见):

static string int2string(int i)
{
    Stack<char> stack = new Stack<char>();
    string s = "";

    do
    {
        stack.Push((char)((i % 10) + 48));
        i = i / 10;
    } while (i > 10);

    stack.Push((char)(i + 48));

    foreach (char c in stack)
    {
        s += c;
    }

    return s;
}
Run Code Online (Sandbox Code Playgroud)

问题是它反向输出字符,所以4238输出是8324.起初,我认为我可以使用x86堆栈来解决这个问题,将数字推入,然后弹出它们并在最后打印它们,但是当我尝试实现该功能时,它失败了,我再也无法获得输出.

结果,我有点困惑的是我如何在这个算法中实现一个堆栈,以实现我的目标,即打印一个整数.如果有一个更简单/更好的解决方案,我也会感兴趣(因为它是我的第一个汇编程序之一).

Bre*_*dan 6

一种方法是使用递归.在这种情况下,你将数字除以10(得到一个商和一个余数)然后用商来称呼自己作为要显示的数字; 然后显示与剩余部分对应的数字.

一个例子是:

;Input
; eax = number to display

    section .data
const10:    dd 10
    section .text

printNumber:
    push eax
    push edx
    xor edx,edx          ;edx:eax = number
    div dword [const10]  ;eax = quotient, edx = remainder
    test eax,eax         ;Is quotient zero?
    je .l1               ; yes, don't display it
    call printNumber     ;Display the quotient
.l1:
    lea eax,[edx+'0']
    call printCharacter  ;Display the remainder
    pop edx
    pop eax
    ret
Run Code Online (Sandbox Code Playgroud)

另一种方法是通过更改除数来避免递归.一个例子是:

;Input
; eax = number to display

    section .data
divisorTable:
    dd 1000000000
    dd 100000000
    dd 10000000
    dd 1000000
    dd 100000
    dd 10000
    dd 1000
    dd 100
    dd 10
    dd 1
    dd 0
    section .text

printNumber:
    push eax
    push ebx
    push edx
    mov ebx,divisorTable
.nextDigit:
    xor edx,edx          ;edx:eax = number
    div dword [ebx]      ;eax = quotient, edx = remainder
    add eax,'0'
    call printCharacter  ;Display the quotient
    mov eax,edx          ;eax = remainder
    add ebx,4            ;ebx = address of next divisor
    cmp dword [ebx],0    ;Have all divisors been done?
    jne .nextDigit
    pop edx
    pop ebx
    pop eax
    ret
Run Code Online (Sandbox Code Playgroud)

此示例不会抑制前导零,但这很容易添加.

  • 以 MSD 优先打印顺序打印的另一种标准方法是将数字存储到缓冲区(在堆栈上),如 [如何在没有来自 c 库的 printf 的情况下在汇编级编程中打印整数?](https:/ /stackoverflow.com/a/46301894)。特别是当打印整个字符串与打印一个字符一样便宜时(系统调用甚至只是 stdio 函数调用开销。) (2认同)