Assembly x86 Date to Number - Breaking a string into smaller sections

I'm actually looking to be pointed in the right direction on an issue.

I'm looking to convert a date in x86 Assembly from the format "DD-MMM-YYYY" to a unique number so that it can be bubble sorted later and eventually converted back.

So, when I have a string input ie: .data inDate dw "08-SEP-1993"

And I want to split it up to

day = "08"
month = "SEP"
year = "1993"

So that I can process it further (I'll be converting SEP to "7", ect.)

So my question is what is a simple, efficient way to break the date down (code-wise)? I know I'll need to convert the date format to allow for sorting, but I'm new to Assembly so I'm not positive how to break the string up so I can convert it.

Also, as a second question, how would you convert a number from the string to an actual numerical value?

Thanks!

NOTE: I suppose it should be noted I'm using masm32


Next little program was made with EMU8086 (16 bits), it captures numbers from keyboard as strings, convert them to numeric to compare, and finally it converts a number to string to display. Notice the numbers are captured with 0AH, which requieres a 3-level variable "str". The conversion procedures that you need are at the bottom of the code (string2number and number2string).

.model small

.stack 100h

.data

counter dw ?

msj1    db 'Enter a number: $'
msj2    db 'The highest number is: $'
break   db 13,10,'$'

str     db 6                ;MAX NUMBER OF CHARACTERS ALLOWED (4).
        db ?                ;NUMBER OF CHARACTERS ENTERED BY USER.
        db 6 dup (?)        ;CHARACTERS ENTERED BY USER. 

highest dw 0        

buffer  db 6 dup(?)

.code

;INITIALIZE DATA SEGMENT.
  mov  ax, @data
  mov  ds, ax

;-----------------------------------------
;CAPTURE 5 NUMBERS AND DETERMINE THE HIGHEST.

  mov  counter, 5           ;HOW MANY NUMBERS TO CAPTURE.
enter_numbers:                          

;DISPLAY MESSAGE.
  mov  dx, offset msj1
  call printf

;CAPTURE NUMBER AS STRING.
  mov  dx, offset str
  call scanf

;DISPLAY LINE BREAK.
  mov  dx, offset break
  call printf

;CONVERT CAPTURED NUMBER FROM STRING TO NUMERIC.
  mov  si, offset str       ;PARAMETER (STRING TO CONVERT).
  call string2number        ;NUMBER RETURNS IN BX.

;CHECK IF CAPTURED NUMBER IS THE HIGHEST.
  cmp  highest, bx  
  jae  ignore               ;IF (HIGHEST >= BX) IGNORE NUMBER.
;IF NO JUMP TO "IGNORE", CURRENT NUMBER IS HIGHER THAN "HIGHEST".  
  mov  highest, bx          ;CURRENT NUMBER IS THE HIGHEST.

ignore:  
;CHECK IF WE HAVE CAPTURED 5 NUMBERS ALREADY.
  dec  counter
  jnz  enter_numbers

;-----------------------------------------
;DISPLAY HIGHEST NUMBER.

;FIRST, FILL BUFFER WITH '$' (NECESSARY TO DISPLAY).
  mov  si, offset buffer
  call dollars

;SECOND, CONVERT HIGHEST NUMBER TO STRING.              
  mov  ax, highest
  mov  si, offset buffer
  call number2string

;THIRD, DISPLAY STRING.
  mov  dx, offset msj2
  call printf
  mov  dx, offset buffer
  call printf    

;FINISH PROGRAM.
  mov  ax, 4c00h
  int  21h

;-----------------------------------------
;PARAMETER : DX POINTING TO '$' FINISHED STRING.
proc printf
  mov  ah, 9
  int  21h
  ret
endp    

;-----------------------------------------
;PARAMETER : DX POINTING TO BUFFER TO STORE STRING.
proc scanf
  mov  ah, 0Ah
  int  21h
  ret
endp    

;------------------------------------------
;CONVERT STRING TO NUMBER.
;PARAMETER : SI POINTING TO CAPTURED STRING.
;RETURN    : NUMBER IN BX.

proc string2number
;MAKE SI TO POINT TO THE LEAST SIGNIFICANT DIGIT.
  inc  si ;POINTS TO THE NUMBER OF CHARACTERS ENTERED.
  mov  cl, [ si ] ;NUMBER OF CHARACTERS ENTERED.                                         
  mov  ch, 0 ;CLEAR CH, NOW CX==CL.
  add  si, cx ;NOW SI POINTS TO LEAST SIGNIFICANT DIGIT.
;CONVERT STRING.
  mov  bx, 0
  mov  bp, 1 ;MULTIPLE OF 10 TO MULTIPLY EVERY DIGIT.
repeat:         
;CONVERT CHARACTER.                    
  mov  al, [ si ] ;CHARACTER TO PROCESS.
  sub  al, 48 ;CONVERT ASCII CHARACTER TO DIGIT.
  mov  ah, 0 ;CLEAR AH, NOW AX==AL.
  mul  bp ;AX*BP = DX:AX.
  add  bx, ax ;ADD RESULT TO BX. 
;INCREASE MULTIPLE OF 10 (1, 10, 100...).
  mov  ax, bp
  mov  bp, 10
  mul  bp ;AX*10 = DX:AX.
  mov  bp, ax ;NEW MULTIPLE OF 10.  
;CHECK IF WE HAVE FINISHED.
  dec  si ;NEXT DIGIT TO PROCESS.
  loop repeat ;COUNTER CX-1, IF NOT ZERO, REPEAT.

  ret 
endp    

;------------------------------------------
;FILLS VARIABLE WITH '$'.
;USED BEFORE CONVERT NUMBERS TO STRING, BECAUSE
;THE STRING WILL BE DISPLAYED.
;PARAMETER : SI = POINTING TO STRING TO FILL.

proc dollars                 
  mov  cx, 6
six_dollars:      
  mov  bl, '$'
  mov  [ si ], bl
  inc  si
  loop six_dollars

  ret
endp  

;------------------------------------------
;CONVERT A NUMBER IN STRING.
;ALGORITHM : EXTRACT DIGITS ONE BY ONE, STORE
;THEM IN STACK, THEN EXTRACT THEM IN REVERSE
;ORDER TO CONSTRUCT STRING (STR).
;PARAMETERS : AX = NUMBER TO CONVERT.
;             SI = POINTING WHERE TO STORE STRING.

proc number2string
  mov  bx, 10 ;DIGITS ARE EXTRACTED DIVIDING BY 10.
  mov  cx, 0 ;COUNTER FOR EXTRACTED DIGITS.
cycle1:       
  mov  dx, 0 ;NECESSARY TO DIVIDE BY BX.
  div  bx ;DX:AX / 10 = AX:QUOTIENT DX:REMAINDER.
  push dx ;PRESERVE DIGIT EXTRACTED FOR LATER.
  inc  cx ;INCREASE COUNTER FOR EVERY DIGIT EXTRACTED.
  cmp  ax, 0  ;IF NUMBER IS
  jne  cycle1 ;NOT ZERO, LOOP. 
;NOW RETRIEVE PUSHED DIGITS.
cycle2:  
  pop  dx        
  add  dl, 48 ;CONVERT DIGIT TO CHARACTER.
  mov  [ si ], dl
  inc  si
  loop cycle2  

  ret
endp  

Now the 32 bits version. Next is a little program that assigns to EAX a big number, convert it to string and convert it back to numeric, here it is:

.model small

.586

.stack 100h

.data

msj1   db 13,10,'Original EAX = $'
msj2   db 13,10,'Flipped  EAX = $'
msj3   db 13,10,'New      EAX = $'

buf    db 11
       db ?
       db 11 dup (?)

.code          
start:
;INITIALIZE DATA SEGMENT.
  mov  ax, @data
  mov  ds, ax

;CONVERT EAX TO STRING TO DISPLAY IT.
  call dollars  ;NECESSARY TO DISPLAY.
  mov  eax, 1234567890
  call number2string  ;PARAMETER:AX. RETURN:VARIABLE BUF.

;DISPLAY 'ORIGINAL EAX'.
  mov  ah, 9
  mov  dx, offset msj1
  int  21h  

;DISPLAY BUF (EAX CONVERTED TO STRING).
  mov  ah, 9
  mov  dx, offset buf
  int  21h  

;FLIP EAX.
  call dollars  ;NECESSARY TO DISPLAY.
  mov  eax, 1234567890
  call flip_eax  ;PARAMETER:AX. RETURN:VARIABLE BUF.

;DISPLAY 'FLIPPED EAX'.
  mov  ah, 9
  mov  dx, offset msj2
  int  21h  

;DISPLAY BUF (EAX FLIPPED CONVERTED TO STRING).
  mov  ah, 9
  mov  dx, offset buf
  int  21h  

;CONVERT STRING TO NUMBER (FLIPPED EAX TO EAX).
  mov  si, offset buf  ;STRING TO REVERSE.
  call string2number   ;RETURN IN EBX.
  mov  eax, ebx        ;THIS IS THE NEW EAX FLIPPED.

;CONVERT EAX TO STRING TO DISPLAY IT.
  call dollars  ;NECESSARY TO DISPLAY.
  call number2string  ;PARAMETER:EAX. RETURN:VARIABLE BUF.

;DISPLAY 'NEW EAX'.
  mov  ah, 9
  mov  dx, offset msj3
  int  21h  

;DISPLAY BUF (EAX CONVERTED TO STRING).
  mov  ah, 9
  mov  dx, offset buf
  int  21h  

;WAIT UNTIL USER PRESS ANY KEY.
  mov  ah, 7
  int  21h

;FINISH PROGRAM.
  mov  ax, 4c00h
  int  21h           

;------------------------------------------

flip_eax proc
  mov  si, offset buf  ;DIGITS WILL BE STORED IN BUF.
  mov  bx, 10 ;DIGITS ARE EXTRACTED DIVIDING BY 10.
  mov  cx, 0  ;COUNTER FOR EXTRACTED DIGITS.
extracting:       
;EXTRACT ONE DIGIT.
  mov  edx, 0 ;NECESSARY TO DIVIDE BY EBX.
  div  ebx ;EDX:EAX / 10 = EAX:QUOTIENT EDX:REMAINDER.
;INSERT DIGIT IN STRING.
  add  dl, 48 ;CONVERT DIGIT TO CHARACTER.
  mov  [ si ], dl
  inc  si
;NEXT DIGIT.
  cmp  eax, 0     ;IF NUMBER IS
  jne  extracting ;NOT ZERO, REPEAT.

  ret
flip_eax endp  

;------------------------------------------
;CONVERT STRING TO NUMBER IN EBX.
;SI MUST ENTER POINTING TO THE STRING.

string2number proc

;COUNT DIGITS IN STRING.
  mov  cx, 0
find_dollar:                                          
  inc  cx  ;DIGIT COUNTER.
  inc  si  ;NEXT CHARACTER.
  mov  bl, [ si ]
  cmp  bl, '$'
  jne  find_dollar  ;IF BL != '$' JUMP.
  dec  si  ;BECAUSE IT WAS OVER '$', NOT OVER THE LAST DIGIT.

;CONVERT STRING.
  mov  ebx, 0
  mov  ebp, 1 ;MULTIPLE OF 10 TO MULTIPLY EVERY DIGIT.
repeat:         
;CONVERT CHARACTER.                    
  mov  eax, 0 ;NOW EAX==AL.
  mov  al, [ si ] ;CHARACTER TO PROCESS.
  sub  al, 48 ;CONVERT ASCII CHARACTER TO DIGIT.
  mul  ebp ;EAX*EBP = EDX:EAX.
  add  ebx, eax ;ADD RESULT TO BX. 
;INCREASE MULTIPLE OF 10 (1, 10, 100...).
  mov  eax, ebp
  mov  ebp, 10
  mul  ebp ;AX*10 = EDX:EAX.
  mov  ebp, eax ;NEW MULTIPLE OF 10.  
;CHECK IF WE HAVE FINISHED.
  dec  si ;NEXT DIGIT TO PROCESS.
  loop repeat ;CX-1, IF NOT ZERO, REPEAT.

  ret 
string2number endp

;------------------------------------------
;FILLS VARIABLE STR WITH '$'.
;USED BEFORE CONVERT NUMBERS TO STRING, BECAUSE
;THE STRING WILL BE DISPLAYED.

dollars proc
  mov  si, offset buf
  mov  cx, 11
six_dollars:      
  mov  bl, '$'
  mov  [ si ], bl
  inc  si
  loop six_dollars

  ret
dollars endp  

;------------------------------------------
;NUMBER TO CONVERT MUST ENTER IN EAX.
;ALGORITHM : EXTRACT DIGITS ONE BY ONE, STORE
;THEM IN STACK, THEN EXTRACT THEM IN REVERSE
;ORDER TO CONSTRUCT STRING (BUF).

number2string proc
  mov  ebx, 10 ;DIGITS ARE EXTRACTED DIVIDING BY 10.
  mov  cx, 0 ;COUNTER FOR EXTRACTED DIGITS.
cycle1:       
  mov  edx, 0 ;NECESSARY TO DIVIDE BY EBX.
  div  ebx ;EDX:EAX / 10 = EAX:QUOTIENT EDX:REMAINDER.
  push dx ;PRESERVE DIGIT EXTRACTED (DL) FOR LATER.
  inc  cx  ;INCREASE COUNTER FOR EVERY DIGIT EXTRACTED.
  cmp  eax, 0  ;IF NUMBER IS
  jne  cycle1  ;NOT ZERO, LOOP. 
;NOW RETRIEVE PUSHED DIGITS.
  mov  si, offset buf
cycle2:  
  pop  dx        
  add  dl, 48 ;CONVERT DIGIT TO CHARACTER.
  mov  [ si ], dl
  inc  si
  loop cycle2  

  ret
number2string endp  

end start