Assembly x86 Date to Number - 将字符串分成更小的部分

2024-01-09

我实际上希望在某个问题上找到正确的方向。

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

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

我想把它分成

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

这样我就可以进一步处理它(我将把 SEP 转换为“7”等)

所以我的问题是,什么是一种简单、有效的方法来分解日期(按代码方式)?我知道我需要转换日期格式以允许排序,但我是汇编新手,所以我不确定如何分解字符串以便我可以转换它。

另外,作为第二个问题,如何将数字从字符串转换为实际的数值?

Thanks!

注意:我想应该注意我正在使用 masm32


接下来的小程序是用EMU8086(16位)编写的,它从键盘上捕获数字作为字符串,将它们转换为数字进行比较,最后将数字转换为字符串进行显示。请注意,数字是用 0AH 捕获的,这需要 3 级变量“str”。您需要的转换过程位于代码底部(字符串2数字 and 数字2字符串).

.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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Assembly x86 Date to Number - 将字符串分成更小的部分 的相关文章

  • 错误:无法识别的指令 [ORG]

    我试图编写一个引导加载程序以在 dos box 中使用 我写了下面的代码 BITS 16 tell the assembler that its a 16 bit code ORG 0x7C00 Origin tell the assemb
  • 在 qemu 中将扇区加载到 RAM

    我编写了一个简单的程序 将扇区 扇区编号 2 加载到 RAM 但什么也没打印 首先 我尝试了以下引导扇区代码 org 0x7c00 mov ax 0x1000 ES BX 1000 0000 mov es ax mov bx 0x00 Lo
  • C# 使文本框中的一组字符表现得像一个字符

    基本上 我有这样的关键字sin and cos 在文本框中 我希望它的行为像单个字符 当我在下面提到整个字符串时 它指的是字符组 例如 sin Using sin 举个例子 如果插入符号位于此位置 在s 如果你按下del 它将删除整个字符串
  • 如何从程序内部获取指向程序的特定可执行文件部分的指针? (也许是诽谤)

    我在 Linux 环境中 需要编写一个程序来检索放置在其可执行文件的某个部分中的一些数据 那么 如何从程序内部获取指向程序某个部分 通过其名称 的指针呢 我知道可以使用elf getdata 将节的索引作为参数传递给 get 和Elf Da
  • 为什么使用 string::iterator 而不是索引? [复制]

    这个问题在这里已经有答案了 可能的重复 为什么使用迭代器而不是数组索引 https stackoverflow com questions 131241 why use iterators instead of array indices
  • 字符串文字会被编译器优化吗?

    C 编译器或 NET CLR 是否对字符串文字 常量进行了任何巧妙的内存优化 我可以发誓我听说过 字符串内化 的概念 因此在程序中的任何两位代码中 文字 这是一个字符串 实际上会指代同一个对象 大概是安全的 对于字符串来说是这样的 不可变
  • 打印“X”个字符数与“X”字符串长度的所有可能组合(暴力破解)

    我正在尝试编写一个单词组合生成器 我的意思是打印 X 个字符数与 X 字符串长度的所有可能组合 首先 我需要说的是 我在 StackOverFlow 中看到了一个关于这个问题的问题 其中有很多单词生成器的答案来执行此操作 在不同的语言上 但
  • 检查字符串是否编码为 UTF-8

    function seems utf8 str length strlen str for i 0 i lt length i c ord str i if c lt 0x80 n 0 0bbbbbbb elseif c 0xE0 0xC0
  • 为什么 JavaScript 中是 [1,2] + [3,4] = "1,23,4" ?

    我想将一个数组的元素添加到另一个数组中 所以我尝试了以下方法 1 2 3 4 它的回应是 1 23 4 到底是怎么回事 The 操作员没有为数组定义 发生的事情是 JavaScript将数组转换为字符串并将它们连接起来 Update 由于这
  • JavaScript:搜索字符串时的 indexOf 与 Match? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 使用之间是否存在明显的性能差异 str indexOf src and str match src 我个人比较喜欢match 和正则表达式 但同
  • NASM:如何正确访问SSD驱动器?

    我需要使用 NASM 16 位代码访问 SSD 驱动器 访问普通硬盘时 需要设置寄存器AX DX CX来选择柱面 磁道 扇区 扇区数 AH 选择读扇区功能 DL 选择驱动器号 CH 选择气缸 DH 选择磁盘上的一侧 CL 选择步入正轨的部门
  • 正则表达式:如何从字符串中获取单词(C#)

    我的输入由用户发布的字符串组成 我想做的是创建一本包含单词以及它们的使用频率的字典 这意味着我想解析一个字符串 删除所有垃圾 并获取单词列表作为输出 例如 假设输入是 LOLOLOL YOU VE BEEN PWN3D 1einszwei
  • 如何将 SQL 结果存入 STRING 变量?

    我正在尝试获取 C 字符串变量或字符串数 组中的 SQL 结果 是否可以 我需要以某种方式使用 SqlDataReader 吗 我对 C 函数和所有功能非常陌生 曾经在 PHP 中工作 所以如果可以的话请给出一个工作示例 如果相关 我已经可
  • 为什么 GCC 在堆栈上压入额外的返回地址?

    我目前正在学习汇编的基础知识 在查看 GCC 6 1 1 生成的指令时遇到了一些奇怪的情况 这是来源 include
  • 将字节数组编码解码为字符串而不丢失数据

    我尝试将 byte 转换为字符串 如下所示 Map
  • PHP中特殊字符的转换

    我已经尝试了很多功能 但我根本无法弄清楚这一点 无论如何 正确的方法 在称为描述的表单字段中 我可以期待各种字符 在将它们提交到数据库之前 需要将它们格式化为 HTML 实体 现在 我的代码 formdesc htmlentities PO
  • MySql 查询在选择中将 NULL 替换为空字符串

    如何用空字符串替换 select 中的 NULL 值 输出 NULL 值看起来不太专业 这是非常不寻常的 根据我的语法 我希望它能够工作 我希望能得到一个解释 为什么没有 select CASE prereq WHEN prereq IS
  • Python,将字典存储在数据库中

    在数据库中存储和检索 python 字典的最佳方法是什么 如果您对使用传统 SQL 数据库 例如 MySQL 不是特别感兴趣 您可以研究非结构化文档数据库 其中文档自然映射到 python 字典 例如MongoDB http www mon
  • C++:字符串流有什么好处?

    谁能告诉我一些在 C 中使用字符串流的实际例子 即使用流插入和流提取运算符输入和输出到字符串流 您可以使用字符串流来转换任何实现operator lt lt 到一个字符串 include
  • 正则表达式 - 避免表达式中出现字符串

    我正在尝试创建一个应该匹配以下情况的正则表达式 如果单词完全匹配 first second third 那么匹配应该失败 但如果它周围有任何字符 那么应该匹配该字符串 我还需要避免字符串中的某些字符集 如果这些字符是字符串的一部分 则匹配结

随机推荐