Assembly x86 Date to Number - 将字符串分成更小的部分 [英] Assembly x86 Date to Number - Breaking a string into smaller sections

查看:14
本文介绍了Assembly x86 Date to Number - 将字符串分成更小的部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我实际上希望在某个问题上指向正确的方向.

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

我希望将 x86 程序集中的日期从格式DD-MMM-YYYY"转换为唯一数字,以便稍后可以对其进行冒泡排序并最终转换回来.

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.

所以,当我有一个字符串输入时,即:.数据日期 dw "08-SEP-1993"

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

我想把它分成

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

以便我可以进一步处理它(我会将 SEP 转换为7"等)

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?

谢谢!

注意:我想应该注意我使用的是 masm32

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

推荐答案

下一个小程序是用 EMU8086(16 位)做的,它从键盘上捕获数字作为字符串,将它们转换为数字进行比较,最后它转换一个数字要显示的字符串.请注意,数字是用 0AH 捕获的,这需要一个 3 级变量str".您需要的转换程序位于代码底部(string2numbernumber2string).

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  

现在是 32 位版本.接下来是一个小程序,给 EAX 分配一个大数字,将其转换为字符串,然后再转换回数字,如下所示:

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

这篇关于Assembly x86 Date to Number - 将字符串分成更小的部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆