Author Topic: how to print numbers to 32 bit messagebox  (Read 9391 times)

Offline william427

  • Jr. Member
  • *
  • Posts: 23
how to print numbers to 32 bit messagebox
« on: July 25, 2014, 05:19:48 PM »
to print numbers to a 32 bit messagebox  do you all ways have to convert it ?
thanks

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: how to print numbers to 32 bit messagebox
« Reply #1 on: July 25, 2014, 06:54:39 PM »
Yeah, pretty much. This prints factorials until they overflow (20! ?). It is very old - obsolete "-f obj" format. It might still work... or maybe can be tweaked to work.

Code: [Select]
; assemble: nasm -f obj file.asm
; link: alink -oPE file.obj win32.lib

extern MessageBoxA
extern ExitProcess

segment data use32

    title1: db 'Factorials',0
    title2  db 'Game Over!',0
    overmsg db 'Overflows 64 bits!',0

segment bss use32
    buffer resb 80h

segment code use32

..start

    mov ecx,1          ; start with n=1
nextfact:
                       ; show n
    xor edx,edx        ; clear high dword - we don't want it
    mov eax,ecx        ; edx:eax = n
    mov edi,buffer      ; buffer for "conversion"
    call U64TODA       ; 64 bit number to string at edi
    mov al,'!'
    stosb
    mov al,' '
    stosb
    mov al,'='
    stosb
    mov al,' '
    stosb
   
    mov eax,1          ; set up for mult loop
    push ecx           ; save our old n - loop will decrement ecx
factmult:
    mov ebx,eax        ; save old low dword
    mov eax,edx        ; multiply old high dword
    mul ecx            ; by n, n-1, n-2, etc
    or edx,edx         ; have we got a "too high" dword?
    jnz overflow       ; bail out if we do
    xchg ebx,eax       ; get old low dword back, stash new high dword
    mul ecx            ; multiply the low dword by n, n-1,...
    add edx,ebx        ; add high dword result to high dword from this mult
    jc overflow        ; does that put us over 64 bits?
    loop factmult      ; dec ecx (n) and repeat if not zero

                       ; show n!
    call U64TODA

    push dword 01h ; OK button
    push dword title1
    push dword buffer
    push dword 0
    call MessageBoxA

    cmp eax,1
    jz noexit
    pop ecx
    jmp exit
noexit:

    pop ecx               ; get our last n back
    inc ecx               ; bump it
    jmp nextfact          ; and do the next one

overflow:
    pop ecx            ; we had it saved on stack when we exited loop
    mov esi,overmsg
copy:
    lodsb
    stosb
    or al,al
    jnz copy

    push dword 01h ; OK button
    push dword title2
    push dword buffer
    push dword 0
    call MessageBoxA
exit:
    push dword 0
    call ExitProcess

;--------------------------------------------------------------
; U64TODA - converts (64 bit) integer in edx:eax
; to (comma delimited) decimal representation in
; zero terminated string in buffer pointed to by edi
; returns with edi pointed to the zero
;-----------------------------------------------------------------
U64TODA :
                push eax
                push ebx
                push ecx
                push edx
                push esi

                mov ebx,edx     ; stash high dword
                mov esi,0Ah     ; prepare to divide by 10
                xor ecx,ecx     ; zero the digit count
                jmp highleft    ; check is high dword 0 ?
highword:
                xchg eax,ebx    ; swap high & low dwords
                xor edx,edx     ; zero edx for the divide!
                div esi         ; divide high dword by 10
                xchg eax,ebx    ; swap 'em back
                div esi         ; divide low dword including remainder
                push edx        ; remainder is our digit - save it
                inc ecx         ; count digits
highleft:
                or ebx,ebx
                jnz highword
lowleft:
                xor edx,edx          ; zero high dword
                div esi              ; divide low dword by 10
                push edx             ; our digit
                inc ecx              ; count it
                or eax,eax           ; 0 yet ?
                jne lowleft
                cmp ecx,04h          ; commas needed ?
                jl write2buf         ; nope
                xor edx,edx          ; zero high dword for divide
                mov eax,ecx          ; number of digits
                mov ebx,3
                div ebx
                mov esi,edx          ; remainder = number digits before comma
                or edx,edx
                jnz write2buf        ; no remainder?
                mov esi,3            ; we can write 3 digits, then.
write2buf:
                pop eax              ; get digit back - in right order
                add al,30H           ; convert to ascii character
                stosb                ; write it to our buffer
                dec esi              ; digits before comma needed
                jnz moredigits       ; no comma needed yet
                cmp ecx,2            ; we at the end?
                jl moredigits        ; don't need comma
                mov al,','           ; write a comma
                stosb
                mov esi,03h          ; we're good for another 3 digits
moredigits:
                loop write2buf       ; write more digits - cx of 'em
                mov al,00h           ; terminate buffer with zero
                stosb
                dec edi

                pop esi
                pop edx
                pop ecx
                pop ebx
                pop eax
                ret
;-------------------------------------------------------------

This is far from optimized. Used to work, as I recall. Might, still. Good luck!

Best,
Frank


Offline nullptr

  • Jr. Member
  • *
  • Posts: 27
Re: how to print numbers to 32 bit messagebox
« Reply #2 on: July 26, 2014, 05:59:26 AM »
You can use wsprintf to convert binary digit and paste it into string:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms647550%28v=vs.85%29.aspx
Code: [Select]
;assemble:
;nasm.exe -f win32 wsprintf.asm -o wsprintf.obj
;link:
;golink /entry main wsprintf.obj user32.dll

bits 32

extern MessageBoxA
extern wsprintfA

MB_OK EQU 0

section .data

Caption DB "wsprintf test",0
Fmt DB "ASCII number: %u",0

section .bss
MsgOut resb 32


section .text

main:
mov eax, 123456789

push eax
push Fmt
push MsgOut
call wsprintfA

push MB_OK
push Caption
push MsgOut
push 0
call MessageBoxA

ret

Offline gammac

  • Jr. Member
  • *
  • Posts: 71
  • Country: 00
Re: how to print numbers to 32 bit messagebox
« Reply #3 on: July 26, 2014, 11:25:12 AM »
wsprintf is __cdecl, the caller have to clean the stack.
Please comment your code! It helps to help you.

Offline nullptr

  • Jr. Member
  • *
  • Posts: 27
Re: how to print numbers to 32 bit messagebox
« Reply #4 on: July 26, 2014, 12:37:31 PM »
Quote
wsprintf is __cdecl, the caller have to clean the stack.
Yes, sorry i forgot to restore esp. After call wsprintfA should be:

Code: [Select]
add esp, 4*3

thanks gammac.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: how to print numbers to 32 bit messagebox
« Reply #5 on: July 26, 2014, 12:50:15 PM »
... and besides, it doesn't put commas in. :)

Seriously, thanks for the example and the correction. I would have expected that with the stack altered, ending with "ret" would have crashed hard. Didn't it? I was under the impression that "ExitProcess" was the prefered way to exit.

Still, one way or another, yeah you have to convert the numbers.

Best,
Frank


Offline nullptr

  • Jr. Member
  • *
  • Posts: 27
Re: how to print numbers to 32 bit messagebox
« Reply #6 on: July 26, 2014, 01:58:22 PM »
Quote
Seriously, thanks for the example and the correction. I would have expected that with the stack altered, ending with "ret" would have crashed hard. Didn't it? I was under the impression that "ExitProcess" was the prefered way to exit.
It runs like lightning - lol. No crash at all. But that's true it should crash without ExitProcess.

 I'm rather user of other assemblers than NASM so sometimes confused about it. I took idea of "ret" at the end becuase I saw some GCC linked examples that are exiting in this way(doesn't remeber them well so maybe those are my delusions :) ).

Sorry for my mess. Maybe i'll became programmer in next life. Anyway thanks for corrections.
« Last Edit: July 26, 2014, 02:01:21 PM by nullptr »

Offline gammac

  • Jr. Member
  • *
  • Posts: 71
  • Country: 00
Re: how to print numbers to 32 bit messagebox
« Reply #7 on: July 26, 2014, 03:05:58 PM »
I would have expected that with the stack altered, ending with "ret" would have crashed hard. Didn't it? I was under the impression that "ExitProcess" was the prefered way to exit.

Yes, it'll crashes and yes, ExitProcess is the prefered way to exit.
Please comment your code! It helps to help you.