I for one, have no particular bias and if there is a way of doing something better, I want to learn it. Space to me is the primary concern, as grandiose as it may seem, but I do aspire to have my entire system fit on a high density floppy. Without knowing the specifics of my design intent, that statement doesn't mean much, but I do know I have to avoid any sort of bloat.
One thing I've come to learn in "C" and maybe because I'm not doing it right, is that the linker will page align each object module. What would be helpful if I was to see an example of how something would be coded in "C" to match or nearly approximate this example. I believe it would be called something like this;
char *Str = I2H ( long Value, int Position, int Flags ) {
.... Whatever need to happen here ....
}
Code:
; ============================================================================================
; Converts 32/16 bit value in E(AX) to an ASCIIZ string.
; ENTER: ARG3: Flags & padd character
; ARG2: Pointer to last digit position in ASCIIZ buffer
; ARG1: Value to be converted, must be 32 bit even if only converting 16
; LEAVE: AX = Pointer to beginning of ASCIIZ buffer
; Only CX & DX altered
; FLAGS: Unchanged
; 2015.05.05 4FH - 79 Bytes
; --------------------------------------------------------------------------------------------
; Arguments passed by caller
%define VALUE BP + 4 ; Arg 1: 16/32 bit value to be converted
%define BUFF BP + 8 ; Arg 2: Pointer last position ASCIIZ buffer
%define FILL_CH BP + 10 ; Arg 3: Flags & fill character
%define FLAGS BP + 11
; Bit positions in FLAGS
%define PADD 0 ; Leading chars will be filled with FILL_CH
%define WIDE 1 ; 32 bit conversion if ON
%define CASE 5 ; A-F will be converted to lower case
I2H: push bp
mov bp, sp ; Empty proc frame so BP can address args.
push di ; Preserve
; This guarantees DF will be returned to its original state even if it's already set.
pushf
std ; Auto decrement STOSB
; Initialize registers for converesion loop
mov eax, [VALUE] ; Get 32 bit value, only 16 might be significant
mov di, [BUFF] ; Get pointer to ASCIIZ string. ES already set
mov dl, [FLAGS]
mov cx, 8 ; Default 16 bit converesion
bt dx, WIDE
jc .Next ; Flag OFF, doing 16 bit conversion
; In order to guarantee padding works correctly, MSB of EAX needs to be striped
; otherwise output will be padded with zeros reguardless.
shr cx, 1
and eax, 0xffff ; Strip bits 31-16 just in case
; Cycle until either EAX or AX is zero or CX is zero.
.Next: push ax
and al, 15 ; Strip bits 7-4
or al, '0' ; Convert to digit
cmp al, '9' ; Is AL a letter
jbe .J0
; Convert to alpha and optionally lower case
add al, 7 ; Convert to alphabetic character
bt dx, CASE
jnc .J0
or al, 32 ; Convert to lower case
; Keep writing characters until E(AX) is null or CX is null
.J0: stosb ; Write to buffer
pop ax
shr eax, 4 ; Shift next digit position into AL
loopnz .Next ; Continue until either ZF=1 or CX=0
; Determine if caller wants to padd remainder of buffer
bt dx, PADD
jnc .Done
mov al, [FILL_CH] ; Get fill character from parameters
rep stosb ; Fill remainder of buffer if CX > 0
.Done: popf ; DF is restored to its original state
mov ax, di ; Return pointer to begining of buffer in AX
pop di
leave ; Kill procedure frame
ret 8 ; Waste parameters
If "C" can do this at least within 100 bytes, then I'll seriously consider changing what I do, but with all that needs to be done and fit in 1.4 meg, I need be thrifty. Just one caveat, no in-line assembly. That is one of the reasons I went to assembly to begin with.
Let's too dispense with any rhetoric. To paraphrase @SpyderTL slightly, from operators perspective, cpu operating at 3.8 gig, time is negligible. I believe there to be many proficient "C" & "C++" programmers, but if an example is not forthcoming, I think it will be safe to assume, it can't be done.