Assembly x86 Date to Number – Rompiendo una cadena en secciones más pequeñas

De hecho, estoy tratando de apuntar en la dirección correcta sobre un problema.

Estoy tratando de convertir una fecha en ensamblaje x86 del formato “DD-MMM-YYYY” a un número único para que se pueda clasificar con una burbuja más adelante y, finalmente, convertir de nuevo.

Entonces, cuando tengo una entrada de cadena, es decir: .data inDate dw “08-SEP-1993”

Y quiero dividirlo para

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

Para poder procesarlo más (voy a convertir SEP a “7”, etc.)

Entonces mi pregunta es ¿cuál es una forma simple y eficiente de romper la fecha (en cuanto al código)? Sé que tendré que convertir el formato de fecha para permitir la clasificación, pero soy nuevo en Assembly, así que no estoy seguro de cómo romper la cadena para poder convertirla.

Además, como segunda pregunta, ¿cómo convertirías un número de la cadena a un valor numérico real?

¡Gracias!

NOTA: Supongo que debería notarse que estoy usando masm32

El siguiente pequeño progtwig fue hecho con EMU8086 (16 bits), captura los números del teclado como cadenas, los convierte a números para comparar, y finalmente convierte un número en una cadena para mostrar. Observe que los números se capturan con 0AH, lo que requiere una variable de 3 niveles “str”. Los procedimientos de conversión que necesita están en la parte inferior del código ( string2number y 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 

Ahora la versión de 32 bits . El siguiente es un pequeño progtwig que asigna a EAX un número grande, lo convierte en cadena y lo convierte de nuevo en numérico, aquí está:

 .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