2015-05-14 3 views
0

Я нахожусь направленным в правильном направлении по проблеме.Сборка x86 Дата по номеру - Разрушение строки на более мелкие секции

Я ищу для преобразования даты в x86 Собрание из формата «DD-MMM-YYYY» на уникальный номер, чтобы впоследствии его можно было отсортировать пузырьками и в конечном итоге преобразовать обратно.

Так что, когда у меня есть строку ввода, а именно: .data inDate Dw "08-сентября-1993"

И я хочу, чтобы разбить его на

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

Так что я могу (я буду преобразовывать SEP в «7» и т. д.)

Итак, мой вопрос - это простой и эффективный способ сломать дату вниз (по коду)? Я знаю, что мне нужно будет преобразовать формат даты, чтобы разрешить сортировку, но я новичок в Assembly, поэтому я не уверен, как сломать строку, чтобы я мог ее преобразовать.

Также, как второй вопрос, как бы вы преобразовали число из строки в фактическое числовое значение?

Спасибо!

Примечание: Я полагаю, следует отметить, я использую MASM32

+0

Я понимаю, что много, но я в DD-MMM-YYYY как прием для моей процедуры. Итак, я хочу разбить DD-MMM-YYYY на отдельные части, чтобы преобразовать, чтобы я мог организовать его таким образом для сортировки. – tforste

+0

Чтобы отсортировать даты, вам нужен YYYYMMDD, потому что этот формат позволяет сравнивать. Например, вы можете использовать его для сравнения дат рождения и узнать, кто моложе или старше: 20150514 позже 20150502. –

+0

Правильно, я понимаю. Но даты будут поступать как DD-MMM-YYYY, к сожалению, этого не происходит. Итак, что я делаю, это преобразование его в YYYYMMDD, Bubble-Sorting и Outputting. Итак, мой вопрос заключается в том, чтобы заставить меня указывать в правильном направлении на мою процедуру DateToNumber, которая будет принимать парм формата DD-MM-YYYY и возвращать YYYYMMDD-номер. – tforste

ответ

2

Следующая маленькая программа была сделана с EMU8086 (16 бит), он захватывает номера с клавиатуры в виде строк, преобразовывать их в числовой для сравнения, и, наконец, он преобразует число в строку для отображения. Обратите внимание, что цифры фиксируются с помощью 0AH, что требует 3-уровневой переменной «str». Необходимые процедуры преобразования находятся внизу кода (string2number и 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 

Теперь 32 бита версия. Далее это небольшая программа, которая присваивает EAX большого числа, преобразовать его в строку и преобразовать его обратно в цифровой, вот оно:

.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 
+0

Спасибо, я должен уметь адаптировать процедуры преобразования, чтобы получить то, что мне нужно. Это имеет смысл. – tforste

+0

'printf' - не очень хорошее имя для функции, которая просто передает строку в' ah = 9/int 21h', не ища конверсий '% d' или чего-то еще. Может быть, 'DOS_puts' будет лучшим именем (хотя C' puts' добавляет новую строку, и для этого требуется завершение '$' вместо ''\ 0' '). Может быть, просто 'print_string' будет лучше. Это определенно не 'printf', потому что' f' означает «отформатирован». –

+0

Эффективнее работать с наиболее значимой цифрой и накапливать «total * = 10; total + = next_digit'. В asm сумма всегда может оставаться в 'AX', и вам нужна только одна итерация' mul' за цикл. –