NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: william427 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
-
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.
; 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
-
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
;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
-
wsprintf is __cdecl, the caller have to clean the stack.
-
wsprintf is __cdecl, the caller have to clean the stack.
Yes, sorry i forgot to restore esp. After call wsprintfA should be:
add esp, 4*3
thanks gammac.
-
... 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
-
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.
-
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.