How do I print an integer in Assembly Level Programming without printf from the c library?

后端 未结 5 1411
予麋鹿
予麋鹿 2020-11-22 00:07

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 w

5条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-11-22 00:44

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

    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).

    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
    

    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.

    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.

    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.

提交回复
热议问题