x86汇编语言:如何将十六进制寄存器值打印为十进制输出?

时间:2016-03-04 20:47:32

标签: assembly x86 masm32 irvine32

让我们说1A(十六进制为26)存储在EAX寄存器中。如何将其转换为十进制,然后将其显示为输出?有没有欧文功能,还是有其他方法可以做到这一点?

1 个答案:

答案 0 :(得分:0)

我不知道Irvine图书馆是否包含这样的东西;我从未使用过该库。

(我希望我不打算为某人解决家庭作业,只是说'...)

这是使用重复除法/模数在普通x86程序集中非常简单的练习。在C中,基本算法看起来像这样:

void ConvertToDecimal(unsigned int n, char *output)
{
    char buffer[16];
    char *dest = buffer + 15;

    /* Perform repeated division, which outputs digits in reverse
       order.  But we put them in the buffer in reverse order, too,
       so they end up coming out in the correct order overall. */
    *--dest = '\0';
    if (n == 0) {
        *--dest = '0';
    }
    else {
        while (n > 0) {
            *--dest = n % 10 + '0';
            n /= 10;
        }
    }

    /* Copy the generated digits to the output. */
    strcpy(output, dest);
}

装配版本实际上是做同样基本技术的问题。 (从C语言中对问题的高级描述开始,然后将该解决方案移植到汇编是解决此类问题的一种方法。)

首先从eax中的数字开始,以及ebx中指向目标缓冲区的输出指针,你得到的结果如下:

ConvertToDecimal:
    push edi                ; Preserve registers we're going to use.

    sub esp, 16             ; Make room for a local buffer on the stack.
    mov edi, esp            ; edi will act like 'dest' does in the C version.
    mov ecx, 10             ; We'll be repeatedly dividing by 10, and the
                            ; div instruction doesn't let you just say 'div 10'.

    dec edi
    mov byte ptr [edi], 0   ; Write the trailing '\0'.

    cmp eax, 0              ; If n == 0...
    ja l1                   ; If it's more than zero, run the loop.

    dec edi
    mov byte ptr [edi], '0' ; Write a '0' to the output.
    jmp l2

    ; Main division loop.

l1: xor edx, edx            ; Zero out edx in preparation for the division.
    div ecx                 ; Divide and modulus edx|eax by 10.
                            ; eax gets the quotient; edx gets the remainder.

    add edx, '0'            ; Change edx from 0-9 to '0'-'9'.

    dec edi
    mov byte ptr [edi], dl  ; Write the next digit, which is now in dl.

    cmp eax, 0
    ja l1                   ; Go back and do it again until we reach zero.        

    ; Copy the result to the destination.

l2: mov al, byte ptr [edi]  ; Read the next character from edi...
    inc edi
    mov byte ptr [ebx], al  ; ...and write that character to ebx.
    inc ebx

    cmp al, 0               ; Copy until we reach the trailing 0 byte.
    jnz l2

    mov eax, ebx            ; As a bonus for the caller, set the return register
    dec eax                 ; to where we wrote the last byte.

    add esp, 16             ; Clean up the buffer on the stack.
    pop edi                 ; Restore the registers we used.

    ret                     ; And we're done.

为了记录,我没有运行上面的代码,但它应该可以工作。

至于将其显示为输出,您需要使用任何库函数或中断来打印字符串。在'DOS'时代,我刚刚反复呼叫int 10h ......