;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Converts integer to string
|
|
; IN: eax = number to convert
|
|
; IN: edi = base of string buffer
|
|
; OUT: ecx = number of characters written to buffer
|
|
IntToString:
|
|
push eax
|
|
push esi
|
|
push edx
|
|
push edi
|
|
push ebp
|
|
|
|
mov ecx, esi ; store negative original buffer base
|
|
neg ecx ; (used for counting amount of characters)
|
|
|
|
test eax, eax
|
|
jns .not_negative
|
|
|
|
mov BYTE [esi], '-'
|
|
neg eax
|
|
add esi, 1
|
|
|
|
.not_negative:
|
|
|
|
mov edi, esi ; store pointer after potential negative sign character
|
|
mov ebp, 0xcccccccd ; ebp = 32 bit multiplicative reciprocal of 10
|
|
|
|
|
|
.divide_loop:
|
|
mov ebx, eax ; save number in ebx
|
|
|
|
mul ebp
|
|
shr edx, 3 ; edx = quotient
|
|
|
|
lea eax, [edx + edx*4] ; eax = quotient * 10 = (number - remainder)
|
|
add eax, eax ; |
|
|
|
|
sub ebx, eax ; ebx = number - (number - remainder) = remainder
|
|
|
|
add ebx, '0' ; remainder is our digit, turn it ASCII
|
|
mov BYTE [esi], bl ; store ASCII digit to buffer
|
|
lea esi, [esi+1]
|
|
|
|
mov eax, edx ; We need quotient in eax for 'mul'
|
|
|
|
test eax, eax
|
|
jne .divide_loop
|
|
|
|
|
|
|
|
add ecx, esi ; Update amount of characters
|
|
|
|
mov byte [esi], 0x00 ; Add null terminator to end of string
|
|
|
|
lea esi, [esi-1] ; We incremented the buffer pointer once too much
|
|
|
|
.swap_loop:
|
|
cmp edi, esi
|
|
jae .done_swapping
|
|
movzx eax, BYTE [esi]
|
|
movzx edx, BYTE [edi]
|
|
mov BYTE [esi], dl
|
|
mov BYTE [edi], al
|
|
sub esi, 1
|
|
add edi, 1
|
|
jmp .swap_loop
|
|
|
|
.done_swapping:
|
|
|
|
pop ebp
|
|
pop edi
|
|
pop edx
|
|
pop esi
|
|
pop eax
|
|
ret
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Right justifies source string within the given justification width
|
|
; IN: esi = base of string buffer
|
|
; IN: edx = justification width
|
|
; IN: ecx = string length
|
|
; IN: al = padding char
|
|
; ASSUMES: that the justification width > string length
|
|
; ASSUMES: that the size of the string buffer > justification width
|
|
RightJustifyString:
|
|
pushad
|
|
pushfd
|
|
|
|
lea edi, [esi + edx-1]
|
|
lea esi, [esi + ecx-1]
|
|
|
|
sub edx, ecx
|
|
|
|
std ; Move string from the end
|
|
rep movsb ; |
|
|
|
|
mov ecx, edx
|
|
rep stosb ; Pad with AL
|
|
|
|
popfd
|
|
popad
|
|
ret
|
|
|
|
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Copies ecx bytes
|
|
; IN: esi = source
|
|
; IN: edi = destination
|
|
; IN: ecx = number of bytes to copy
|
|
CopyData:
|
|
pushad
|
|
|
|
mov edx, ecx
|
|
and edx, 11b
|
|
shr ecx, 2
|
|
; ecx = quotient, edx = remainder
|
|
|
|
rep movsd
|
|
mov ecx, edx
|
|
rep movsb
|
|
|
|
popad
|
|
ret
|
|
|
|
|
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Puts the stringified version of eax on the stack
|
|
; IN: esi = base of string
|
|
; IN: ecx = string length
|
|
; IN: ah = character attributes
|
|
PrintString:
|
|
push ecx
|
|
push eax
|
|
push edi
|
|
push esi
|
|
|
|
.print_loop:
|
|
mov al, byte [esi]
|
|
mov word [edi], ax
|
|
lea esi, [esi+1]
|
|
lea edi, [edi+2]
|
|
sub ecx, 1
|
|
jnz .print_loop
|
|
|
|
pop esi
|
|
pop edi
|
|
pop eax
|
|
pop ecx
|
|
ret
|