How to print a number in x64 windows Assembly

  • (2 Pages)
  • +
  • 1
  • 2

17 Replies - 4308 Views - Last Post: 11 August 2012 - 10:03 AM

#1 davetheant  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 10-August 12

How to print a number in x64 windows Assembly

Posted 10 August 2012 - 02:57 PM

Hello everyone! I recently began trying to learn assembly for my x64 windows 7 laptop using FASM. I wrote a program to solve the first Project Euler challenge, but I realized I don't know how to display my answer! I figured an easy way would be to make a message box with the message text as my number, so I did the 'divide by 10 and push to stack' algorithm, but it doesn't work. How do I convert a bunch of ascii numbers into outputted text? Thanks

Is This A Good Question/Topic? 0
  • +

Replies To: How to print a number in x64 windows Assembly

#2 GunnerInc  Icon User is online

  • "Hurry up and wait"
  • member icon




Reputation: 858
  • View blog
  • Posts: 2,302
  • Joined: 28-March 11

Re: How to print a number in x64 windows Assembly

Posted 10 August 2012 - 03:02 PM

You can cheat and link to the CRT and use printf/sprintf etc...

If you already converted the number to a string, then you can just pass your string pointer to MessageBox.

What do you have so far? Lets see the goods.
Was This Post Helpful? 0
  • +
  • -

#3 davetheant  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 10-August 12

Re: How to print a number in x64 windows Assembly

Posted 10 August 2012 - 03:12 PM

I would love to just pass it to the messagebox but I don't know how to get it in a string! Here is my (probably) bad code:

I push ten to start so that when Im popping I know when to stop popping (because a digit can never be a 10). I have what I think to be the answer stored in EAX when this starts.
Message2 dq '0',0 


 push [ten]
                divLoop:

                mov rdx,0 ; for division
                movsxd rax,eax ;move answer to rax
                div [ten]
                movsxd rdx,edx  ;store digit into rdx
                push rdx  ;push digit to stack
                cmp eax,10 ; loop until there is one digit left
                ja divLoop

                div [ten]     ;do last digit outside of loop
                movsxd rdx,edx
                push rdx

                popping:
                pop rax
                add rax,48 ; to get to ascii
                add [Message2],rax ;Not sure if I should be adding this number??
                sub rax,48
                cmp rax,10 ;terminating condition 
                jne popping


Was This Post Helpful? 0
  • +
  • -

#4 GunnerInc  Icon User is online

  • "Hurry up and wait"
  • member icon




Reputation: 858
  • View blog
  • Posts: 2,302
  • Joined: 28-March 11

Re: How to print a number in x64 windows Assembly

Posted 10 August 2012 - 03:23 PM

I have no idea what that push [ten] is doing for you.

You need to create a buffer to hold your string.
I think you do it like this in FASM
MyMessge resb SIZEOFBUFFER.

You convert your number to a character, move that value into index zero of your buffer, increase the pointer add another character until complete. Once done, zero terminate the buffer and pass that to MessageBox
Was This Post Helpful? 0
  • +
  • -

#5 davetheant  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 10-August 12

Re: How to print a number in x64 windows Assembly

Posted 10 August 2012 - 03:37 PM

View PostGunnerInc, on 10 August 2012 - 03:23 PM, said:

I have no idea what that push [ten] is doing for you.

You need to create a buffer to hold your string.
I think you do it like this in FASM
MyMessge resb SIZEOFBUFFER.

You convert your number to a character, move that value into index zero of your buffer, increase the pointer add another character until complete. Once done, zero terminate the buffer and pass that to MessageBox


Sorry, I forgot to mention that ten is just a quadword defined as a 10, so that it would divide properly. I heard that you can only push a qword or a byte in x64, and pushing bytes leaves the stack mis-aligned or something, so I just decided to push a qword. I pushed it so that when I was popping the characters back off I knew when to stop popping.

As far as the resb command, I believe it's just rb in FASM. So I've reserved a byte of data now.. what did you mean when you said to put the character into index zero of the byte?
Was This Post Helpful? 0
  • +
  • -

#6 GunnerInc  Icon User is online

  • "Hurry up and wait"
  • member icon




Reputation: 858
  • View blog
  • Posts: 2,302
  • Joined: 28-March 11

Re: How to print a number in x64 windows Assembly

Posted 10 August 2012 - 03:42 PM

reserving 1 byte of data will only hold, well 1 byte!!! Which means it will only hold 1 character. Try to put more into the buffer and you will get a seg fault. For a 64 bit number, I would reserve 24 bytes. With a negative symbol, a 64 byte number will be 20 bytes plus the null will be 21. Its good to create "aligned" buffers so we make it 24.

You don't need all these push/pops, loose track of one and your program can/will go POOF! Your writing for 64bit, use all those extra registers!

Oh, you don't have to quote the post above yours.
Was This Post Helpful? 1
  • +
  • -

#7 davetheant  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 10-August 12

Re: How to print a number in x64 windows Assembly

Posted 10 August 2012 - 03:55 PM

Okay great thanks I understand now! But how do I save things to this buffer and then use it as my MessageBox text?
Was This Post Helpful? 0
  • +
  • -

#8 GunnerInc  Icon User is online

  • "Hurry up and wait"
  • member icon




Reputation: 858
  • View blog
  • Posts: 2,302
  • Joined: 28-March 11

Re: How to print a number in x64 windows Assembly

Posted 10 August 2012 - 04:09 PM

global main

section .bss
MyMessage       resb    12
MessageLen      equ $ - MyMessage

SECTION .text
main:

    mov     eax, 4294967295
    push    MyMessage
    push    eax
    call    ConvertIt

    ; your message box call here.
    mov     edx, MessageLen
    mov     ecx, MyMessage
    mov     eax, sys_write
    mov     ebx, stdout
    int     80H

    mov     eax, sys_exit
    xor     ebx, ebx
    int     80H

ConvertIt:
    push    ebp
    mov     ebp, esp
    push    esi
    push    edi
    push    ebx

    mov     eax, [ebp + 8]              ; num to conver
    mov     edi, [ebp + 12]             ; buffer to hold converted num
    add     edi, 12                     ; mov pointer to end
    mov     byte [edi], 0               ; NULL termiate it
    mov     ecx, 10                     ;

.next:
    xor     edx, edx
    test    eax, eax                    ; are we done?
    je      .done

    div     ecx                         ;
    add     dl, 48                      ; convert to ASCII
    mov     byte [edi], dl              ; move converted number to buffer
    dec     edi                         ; decrease pointer
    jmp     .next

.done:
    pop     ebx
    pop     edi
    pop     esi
    mov     esp, ebp
    pop     ebp
    ret


It won't handle signed numbers, and is 32bit, a little lesson for you to convert it. Using NASM/Linux here but it is close to FASM. Where it says
; your message box call here.   ;
    mov     edx, MessageLen         ;
    mov     ecx, MyMessage          ;
    mov     eax, sys_write          ;
    mov     ebx, stdout             ;
    int     80H                     ;
Replace it with something like
    push    NULL
    push    MB_OK
    push    MyMessage
    push    HWND_DESKTOP
    call    MessageBoxA

Was This Post Helpful? 1
  • +
  • -

#9 davetheant  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 10-August 12

Re: How to print a number in x64 windows Assembly

Posted 10 August 2012 - 04:23 PM

I guess I'm still a bit lost on what the ESI / EDI registers do exactly and why you were moving things to EDI?
Was This Post Helpful? 0
  • +
  • -

#10 GunnerInc  Icon User is online

  • "Hurry up and wait"
  • member icon




Reputation: 858
  • View blog
  • Posts: 2,302
  • Joined: 28-March 11

Re: How to print a number in x64 windows Assembly

Posted 10 August 2012 - 04:33 PM

Are you in school? Even if you are, I urge you read a few tutorials on memory in Assembly.
EDI contains the pointer to our string/buffer. You convert a character, move that character into our buffer at the pointer in edi. Increase/decrease the pointer to add other characters.
Was This Post Helpful? 0
  • +
  • -

#11 davetheant  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 10-August 12

Re: How to print a number in x64 windows Assembly

Posted 10 August 2012 - 06:17 PM

Yes I'm in school (though not taking an ASM class) and read many tutorials on FASM and have searched (on Google) specifically on how to use the EDI/ESI registers and about string operations but I haven't found anything that explains it, which is why I'm asking on here. Is it correct to say that I should point the di register to my buffer's address and then move my character to si and perform 'movs'? I really don't understand why this works or how it works.
Was This Post Helpful? 0
  • +
  • -

#12 davetheant  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 10-August 12

Re: How to print a number in x64 windows Assembly

Posted 10 August 2012 - 07:17 PM

Okay so I took a slightly different approach. I know that the answer has 6 digits and I know my algorithm for computing the answer works as I did it in another language and got the right answer. Here's part of my new code:

Jer rb 128 ; buffer
Message2 dq '0',0
ten       dq      10  


                mov rcx, Jer ;put buffer address into rcx
                add rcx,6       ; add length of number
                mov rdi, rcx   ;move to destination register
                mov qword rsi, 0 ; load 0 into the source register
                movsq

                Loopp:
                dec rdi 
                mov qword rdx,0
                div [ten]
                movsxd rdx,edx ; store dig onto rdx
                add rdx,48 ;convert to ascii
                mov rsi,rdx 
                movsq
                ;inc [numdigs]
                cmp eax,0
                jne Loopp


Is this any better?
Was This Post Helpful? 0
  • +
  • -

#13 GunnerInc  Icon User is online

  • "Hurry up and wait"
  • member icon




Reputation: 858
  • View blog
  • Posts: 2,302
  • Joined: 28-March 11

Re: How to print a number in x64 windows Assembly

Posted 10 August 2012 - 07:23 PM

get rid of line 8, replace rcx with rdi in lines 6 and 7. Replace [ten] in line 15 with a register. Line 21 change to test eax, eax, change line 22 to jnz Looop It is getting there
Was This Post Helpful? 0
  • +
  • -

#14 davetheant  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 10-August 12

Re: How to print a number in x64 windows Assembly

Posted 11 August 2012 - 07:08 AM

Okay thanks a lot that all makes sense. My program still crashes however, so I'm assuming it has something to do with the way I call the MessageBox? I've done the same thing as my Hello World message box, but this time I'm trying to load 'Jer' as my text.
                mov [Message],Jer
                mov r9d, 0
                mov rcx,0
                lea rdx,[Message]
                call [MessageBox]
                invoke ExitProcess,0



Hello world code (which works):
Message db 'Hello World!'


mov r9d,0
mov rcx,0
lea rdx,[Message]
call [MessageBox]
invoke ExitProcess,0 


Was This Post Helpful? 0
  • +
  • -

#15 GunnerInc  Icon User is online

  • "Hurry up and wait"
  • member icon




Reputation: 858
  • View blog
  • Posts: 2,302
  • Joined: 28-March 11

Re: How to print a number in x64 windows Assembly

Posted 11 August 2012 - 08:58 AM

How is Message defined? How is Jer defined? You can't just move things around like you would in a high level language. One line of instruction in C or another language, is usually a few instructions in Assembly.

You don't need to do lea rdx,[Message] you could simply do mov rdx, Message but that won't fix your problem, need to now how Jer is defined, what is it?

I adivse you to spend the weekend reading The Art of Assembly you can disregard the stuff about HLA, it will give you a solid understanding of Assembly
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2