x86 汇编语言:如何将十六进制寄存器值打印为十进制输出?
x86 assembly language: how can I print a hex register value as decimal output?
假设 1A(十六进制为 26)存储在 EAX 寄存器中。如何将其转换为十进制,然后将其显示为输出?是否有任何 Irvine 函数可以做到这一点,或者是否有其他方法可以做到这一点?
我不知道 Irvine 图书馆是否包含这样的东西;我从来没有用过那个库。
(我希望我不是要为某人解决家庭作业,只是说...)
这是一个非常简单的纯 x86 汇编练习,使用重复 division/modulus。在 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 = '[=10=]';
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 '[=11=]'.
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
...
假设 1A(十六进制为 26)存储在 EAX 寄存器中。如何将其转换为十进制,然后将其显示为输出?是否有任何 Irvine 函数可以做到这一点,或者是否有其他方法可以做到这一点?
我不知道 Irvine 图书馆是否包含这样的东西;我从来没有用过那个库。
(我希望我不是要为某人解决家庭作业,只是说...)
这是一个非常简单的纯 x86 汇编练习,使用重复 division/modulus。在 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 = '[=10=]';
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 '[=11=]'.
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
...