简体   繁体   中英

Printing out numbers that are greater then 9 in NASM Assembly

So I am currently following along with this tutorial https://www.tutorialspoint.com/assembly_programming/assembly_arithmetic_instructions.htm and what Im getting from it is that in order to convert a number in ascii to a decimal. I have to subtract it with '0', then perform the math and convert it back to its ascii equivalent by adding it with '0'. However the problem for me arrises when the numbers go beyond 9.

I have a task at hand that requires me to loop through all the contents of a file character by character and keep track of the "count". Im not sure what the best way of going about doing this is but I will show what I have done so far, it definetly does not work and I suspect its because when i convert the "counter" to its ascii value it does exist but it matches some other character that happens to have that decimal value.

section .data
    counter: dd '0' ;holds the num of chars read
section .bss
    Buff resb 1     ;hold the value of one char
    fd_in resb 4
    fd_out resb 4
section .data
global _start
_start:
...
...
...
;increment the counter by 1 each time a char is wrote to file
Add_counter:
    mov eax, [counter]
    sub eax, '0'
    inc eax
    add eax, '0'
    mov [counter], eax
...
...
...
;print out number of characters wrote
Show_num_char:
    mov eax, 4
    mov ebx, 1
    mov ecx, counter
    mov edx, 4
    int 80h
....
...
..

In your case, because you're going for character count, it would be more practical to use the processors natural number system which is binary. Then afterward, convert it to decimal. In this example, let's say you counted 301,927 characters. That would be 0x49b67 in binary. This snippet will do the conversion and then finish with RDI pointing to ASCII converted string.

I don't have a 32 bit machine, so all you have to do is take out the REX qualifiers change registers that start with "r" to "e" and then the same will work for you.

        section .text
        global  _start

 _start     push    byte 0              ; So ASCII string will be terminated
                                        ; with NULL
            mov     rdi, rsp
            mov     eax, 0x49b67        ; = 301927
            mov     ecx, 10

         Div:
            xor     edx, edx
            div     ecx                 ; DL = digit 0 - 9
            or       dl, '0'
            mov     [rdi], dl
            dec     rdi
            or      eax, eax            
            jnz     Div

            inc     rdi                 ; RDI now points to ASCII string

I've left the bit out at the end for exiting the program as in 64 bit I use SYSCALL and you'd use INT 0x80, but follow this through in GDB and you'll see how it works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM