如何在没有 c 库中的 printf 的情况下在汇编级编程中打印整数? [英] How do I print an integer in Assembly Level Programming without printf from the c library?

查看:31
本文介绍了如何在没有 c 库中的 printf 的情况下在汇编级编程中打印整数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

谁能告诉我以十进制格式在寄存器中显示值的纯汇编代码?请不要建议使用 printf hack 然后使用 gcc 编译.

Can anyone tell me the purely assembly code for displaying the value in a register in decimal format? Please don't suggest using the printf hack and then compile with gcc.

说明:

好吧,我对 NASM 进行了一些研究和一些实验,并认为我可以使用 c 库中的 printf 函数来打印一个整数.我通过使用 GCC 编译器编译目标文件来做到这一点,并且一切正常.

Well, I did some research and some experimentation with NASM and figured I could use the printf function from the c library to print an integer. I did so by compiling the object file with the GCC compiler and everything works fair enough.

但是,我想要实现的是以十进制形式打印存储在任何寄存器中的值.

However, what I want to achieve is to print the value stored in any register in the decimal form.

我做了一些研究,发现 DOS 命令行的中断向量 021h 可以显示字符串和字符,而 2 或 9 在 ah 寄存器中,数据在 dx 中.

I did some research and figured the interrupt vector 021h for DOS command line can display strings and characters whilst either 2 or 9 is in the ah register and the data is in the dx.

结论:

我发现的所有示例都没有展示如何在不使用 C 库的 printf 的情况下以十进制形式显示寄存器的内容值.有谁知道如何在汇编中做到这一点?

None of the examples I found showed how to display the content value of a register in decimal form without using the C library's printf. Does anyone know how to do this in assembly?

推荐答案

您需要编写一个二进制到十进制的转换例程,然后使用十进制数字产生数字字符"进行打印.

You need to write a binary to decimal conversion routine, and then use the decimal digits to produce "digit characters" to print.

您必须假设某处某处会在您选择的输出设备上打印一个字符.调用这个子程序print_character";假设它在 EAX 中使用字符代码并保留所有寄存器..(如果您没有这样的子例程,则您有一个额外的问题,应该是另一个问题的基础).

You have to assume that something, somewhere, will print a character on your output device of choice. Call this subroutine "print_character"; assumes it takes a character code in EAX and preserves all the registers.. (If you don't have such a subroutine, you have an additional problem that should be the basis of a different question).

如果您在寄存器(例如 EAX)中有一个数字的二进制代码(例如,0-9 的值),您可以通过添加 ASCII 代码来将该值转换为该数字的字符零"字符到寄存器.这很简单:

If you have the binary code for a digit (e.g., a value from 0-9) in a register (say, EAX), you can convert that value to a character for the digit by adding the ASCII code for the "zero" character to the register. This is as simple as:

       add     eax, 0x30    ; convert digit in EAX to corresponding character digit

然后您可以调用print_character来打印数字字符代码.

You can then call print_character to print the digit character code.

要输出任意值,您需要挑选数字并打印出来.

To output an arbitrary value, you need to pick off digits and print them.

从根本上挑选数字需要使用十的幂.最容易使用 10 的幂,例如 10 本身.想象一下,我们有一个除以 10 的例程,它在 EAX 中取一个值,并在 EDX 中产生一个商,在 EAX 中产生一个余数.我把它留作练习,让你弄清楚如何实现这样的例程.

Picking off digits fundamentally requires working with powers of ten. It is easiest to work with one power of ten, e.g., 10 itself. Imagine we have a divide-by-10 routine that took a value in EAX, and produced a quotient in EDX and a remainder in EAX. I leave it as an exercise for you to figure out how to implement such a routine.

然后一个带有正确想法的简单例程是为该值可能具有的所有数字生成一个数字.32 位寄存器可存储 40 亿个值,因此您可能会打印 10 位数字.所以:

Then a simple routine with the right idea is to produce one digit for all digits the value might have. A 32 bit register stores values to 4 billion, so you might get 10 digits printed. So:

         mov    eax, valuetoprint
         mov    ecx, 10        ;  digit count to produce
loop:    call   dividebyten
         add    eax, 0x30
         call   printcharacter
         mov    eax, edx
         dec    ecx
         jne    loop

这有效...但以相反的顺序打印数字.哎呀!好吧,我们可以利用下推堆栈来存储产生的数字,然后以相反的顺序弹出它们:

This works... but prints the digits in reverse order. Oops! Well, we can take advantage of the pushdown stack to store digits produced, and then pop them off in reverse order:

         mov    eax, valuetoprint
         mov    ecx, 10        ;  digit count to generate
loop1:   call   dividebyten
         add    eax, 0x30
         push   eax
         mov    eax, edx
         dec    ecx
         jne    loop1
         mov    ecx, 10        ;  digit count to print
loop2:   pop    eax
         call   printcharacter
         dec    ecx
         jne    loop2

留给读者练习:取消前导零.此外,由于我们将数字字符写入内存,因此我们可以将它们写入缓冲区,而不是将它们写入堆栈,然后打印缓冲区内容.也留给读者作为练习.

Left as an exercise to the reader: suppress leading zeros. Also, since we are writing digit characters to memory, instead of writing them to the stack we could write them to a buffer, and then print the buffer content. Also left as an exercise to the reader.

这篇关于如何在没有 c 库中的 printf 的情况下在汇编级编程中打印整数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆