Here's a complete command-line program using fasm (exe attached). format PE console
entry start
include 'win32wx.inc'
.code
; Enter with EAX pointing to the suffix (first two wide characters).
; If the suffix is found its value is put on the FPU stack and carry is cleared,
; otherwise 1 is put and carry is set.
get_unit:
mov esi, units
mov eax, [eax]
.repeat
.if dword[esi] = eax
fld qword[esi+4]
clc
ret
.endif
add esi, 12
.until esi = units_end
fld1
stc
ret
start:
invoke CommandLineToArgvW, invoke GetCommandLine, args
.if [args] <> 4
cinvoke printf, help
invoke ExitProcess, 1
.endif
lea ebx, [eax+4]
cinvoke _wtof, dword[ebx]
mov eax, [ebx+4]
call get_unit
fmulp
mov eax, [ebx+8]
call get_unit
fdivp
fld qword[one_thou-8]
fcomip st, st1
mov eax, fmtf
mov ecx, fmtg
cmovae eax, ecx
sub esp, 8
fstp qword[esp]
cinvoke printf, eax
invoke ExitProcess, 0
help db "fsize SIZE IN-UNIT OUT-UNIT", 10
db 10
db "Units are B, KB, Ki, MB, Mi, GB, Gi, TB or Ti.",10
db 0
fmtg db "%.3g", 10, 0
fmtf db "%.0f", 10, 0
struct UNITS
suffix du 2 dup (?)
value dq ?
ends
align 4
units UNITS "B", 1.0
UNITS "KB", 1000.0
one_thou:
UNITS "Ki", 1024.0
UNITS "MB", 1000000.0
UNITS "Mi", 1048576.0
UNITS "GB", 1000000000.0
UNITS "Gi", 1073741824.0
UNITS "TB", 1000000000000.0
UNITS "Ti", 1099511627776.0
units_end:
section '.bss' readable writeable
args dd ?
section '.idata' import data readable writeable
library kernel32,'KERNEL32.DLL',\
msvcrt,'MSVCRT.DLL',\
shell32,'SHELL32.DLL'
include 'api\kernel32.inc'
import shell32,\
CommandLineToArgvW,'CommandLineToArgvW'
import msvcrt,\
printf,'printf',\
_wtof,'_wtof'
I've chosen to go with decimal and binary units, rather than an additional number. E.g. "64.2 MB Mi" converts decimal to binary and "64.2 Mi MB" converts binary to decimal. If the unit isn't recognised it will be ignored (it's detected, though, so just add your own test). The output is three significant digits for numbers under 1000, no decimals otherwise.
fsize.exe