如何将4位十六进制数转换为带二的二进制补码

时间:2016-11-23 15:48:04

标签: assembly x86

如何使用neg

将4位十六进制数转换为二进制补码

我想输入一个4位十六进制数,如果是负数,它将切换为正数,然后我想用两种补码技术来查找结果。

例如,如果我输入F520h,则输出将为-F520h = 0AE0h

问题是,当我输入4位数时,它是ASCII格式,如何在不检查0-9,A-F的情况下确定它是数字还是数字。

2 个答案:

答案 0 :(得分:1)

你应该理解为准备为此设计代码的事情:

输入"字符串"存储在内存中("F520h"至少5个字节,可能更多,后面附加一些终结符值) - 取决于您如何读取用户输入的方法,请参阅使用过的API文档。

什么是ASCII表,即如何将单个字符[0-9A-Fa-f]转换为值0 - 15。提示:如果仔细检查'a''A'的编码,您可能会发现如何使用sub(或add)和{{}将其转换为值10 1}}(也为其他字母工作)。将字符and转换为值'0'更加容易。

如何从四个0(4位)值构建16位值。提示:4 * 4位= 16位,因此只能通过位操作来实现,不需要任何乘法/除法运算。

如何测试值是否为负(可能是CPU已经有#34; SF"在16b值构建最后一条指令后为你设置了标志,所以你需要的只是js instruction

如何否定16b值... x86有neg instruction

如何输出结果数字:

将要求您将16位值分解为4个4b值(再次按位操作应该足够,例如0-15and指令可以完成大部分工作。

将那些shr - 0 4位值重新转换为ASCII字符(因此再次了解ASCII编码应该有帮助)。

从输出API调用所需格式的那些字符创建输出字符串(可能需要一些终结符值,或输出的字符串的确切长度)。

如果您对汇编不了解,那么以指令的形式正确编写可能会非常复杂,并且可能需要几天时间。

虽然在算法方面它非常简单(复杂性更多地隐藏在要完成的工作量中),但我希望你能够"看到"我列出的每个要点背后的数学。这些步骤的排列顺序与我脑海中的算法有些相关。

确保您首先了解如何在理论级别(算法)上计算输入的输出,在非常简单的步骤中描述仅涉及基本数值运算(检查8086 CPU ASM指令的概述以了解什么样的操作是"基本"足够用于CPU以及它如何操作数字/位)。

然后,您可以使用少量x86指令集中精力完成每个步骤。

关于您将遇到的特定步骤的堆栈溢出还有很多问题,例如如何打印十六进制值等,因此您可以检查这些想法(只需确保答案的目标平台与您的相同) ,或理解答案背后的想法,所以你可以自己写。)

编辑:BTW,这个任务有另一个主要方法来解决它,因为你只需要否定ASCII编码的十六进制数,你甚至不需要它将它转换成数值,它是什么?可以修改ASCII字符本身以产生15结果。虽然neg有点棘手(但可行)。我记得做this for xor(在C ++中,但这几乎按照ASM指令编写1:1),当需要高性能时,转换为数字并返回字符串的代价太高。

但是如果您正在尝试学习汇编,那么第一种方式可能更好,因此您可以学习和理解所有这些转换以及如何在字符串< - >值之间转换十六进制数字在集会中。

答案 1 :(得分:0)

下一个代码完成工作:用户输入十六进制数字(最多4位数,例如" F520")作为字符串,将字符串转换为ax中的数字,neg应用于ax,结果将转换回十六进制字符串并显示(示例" 0AE0"),您只需复制粘贴并运行它:

.model small
.stack 100h
.data

msg1 db 10,13,10,13,'ENTER 1 TO 4 HEX DIGITS:$'
msg2 db 10,13,'NEG IS:$'
msg3 db 10,13,10,13,'DO YOU WANT TO DO IT AGAIN (Y/N)?$'
msg4 db 10,13,'ILLEGAL CHARACTER- ENTER 0-9 OR A-F:$'

hex  db 5,?,5 dup(?) ;VARIABLE WITH 3 SECTIONS.
buffer  db '0000$'

.code
  mov  ax, @data
  mov  ds, ax

again:

;CLEAR BUFFER (IN CASE IT HOLDS PREVIOUS RESULT).
  call clear_buffer

;DISPLAY 'ENTER 1 TO 4 HEX DIGITS:$'
  mov  ah, 9
  lea  dx, msg1
  int  21h

;CAPTURE HEX NUMBER AS STRING.
  mov  ah, 0ah
  lea  dx, hex
  int  21h

;CONVERT HEX-STRING TO NUMBER.
  lea  si, hex+2        ;CHARS OF THE HEX-STRING.
  mov  bh, [si-1]       ;SECOND BYTE IS LENGTH.
  call hex2number       ;NUMBER RETURNS IN AX.

  neg  ax

;CONVERT NUMBER BACK TO HEX-STRING TO DISPLAY.
  lea  si, buffer
  call number2hex       ;STRING RETURNS IN SI (BUFFER).

;DISPLAY 'NEG IS :$'
  mov  ah, 9
  lea  dx, msg2
  int  21h            

;DISPLAY NUMBER AS STRING.
  mov  ah, 9
  lea  dx, buffer
  int  21h

illegal: ;JUMP HERE WHEN INVALID CHARACTER FOUND.

;DISPLAY 'DO YOU WANT TO DO IT AGAIN (Y/N)?$' 
  mov  ah, 9
  lea  dx, msg3
  int  21h

;CAPTURE KEY.
  mov  ah, 1
  int  21h
  cmp  al,'y'
  je   again
  cmp  al,'Y'
  je   again

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

;---------------------------------------------  
;FILL VARIABLE "BUFFER" WITH "0".
;EVERYTIME THE USER WANTS TO DO IT AGAIN, THE
;PREVIOUS RESULT MUST BE CLEARED.

clear_buffer proc
  lea  si, buffer
  mov  al, '0'
  mov  cx, 4  
clearing:
  mov  [si], al
  inc  si
  loop clearing

  ret
clear_buffer endp

;---------------------------------------------  
;INPUT  : BH = STRING LENGTH (1..4).
;         SI = OFFSET HEX-STRING.
;OUTPUT : AX = NUMBER.

hex2number proc
      MOV  AX, 0       ;THE NUMBER.
   Ciclo:
;---------------------------------------------
;     SHL  AX, 4       ;SHIFT LEFT LOWER 4 BITS.
;SHIFT LEFT AL AND AH MANUALLY 4 TIMES TO SIMULATE SHL AX,4.
      shl  al, 1
      rcl  ah, 1
      shl  al, 1
      rcl  ah, 1
      shl  al, 1
      rcl  ah, 1
      shl  al, 1
      rcl  ah, 1
;---------------------------------------------

      MOV  BL, [ SI ]  ;GET ONE HEX CHAR FROM STRING.

      call validate

      CMP  BL, 'A'     ;BL = 'A'..'F' : LETTER.
      JAE  letterAF    ;BL = '0'..'9' : DIGIT.
   ;CharIsDigit09.
      SUB  BL, 48      ;CONVERT DIGIT TO NUMBER.
      JMP  continue   
   letterAF:               
      SUB  BL, 55      ;CONVERT LETTER TO NUMBER.
   continue: 
      OR   AL, BL      ;CLEAR UPPER 4 BITS.
      INC  SI          ;NEXT HEX CHAR.
      DEC  BH          ;BH == 0 : FINISH.
      JNZ  Ciclo       ;BH != 0 : REPEAT.
   Fin:
      RET
hex2number endp

;---------------------------------------------  
;INPUT : BL = HEX CHAR TO VALIDATE.

validate proc
    cmp bl, '0'
    jb  error     ;IF BL < '0'
    cmp bl, 'F'
    ja  error     ;IF BL > 'F'
    cmp bl, '9'
    jbe ok        ;IF BL <= '9'
    cmp bl, 'A'
    jae ok        ;IF BL >= 'A'
error:    
    pop  ax       ;REMOVE CALL VALIDATE.
    pop  ax       ;REMOVE CALL HEX2NUMBER.
;DISPLAY 'ILLEGAL CHARACTER- ENTER 0-9 OR A-F$'
    mov  ah, 9
    lea  dx, msg4
    int  21h
    jmp  illegal  ;GO TO 'DO YOU WANT TO DO IT AGAIN (Y/N)?$'
ok:    
    ret
validate endp

;---------------------------------------------  
;INPUT : AX = NUMBER TO CONVERT TO DECIMAL.
;        SI = OFFSET STRING TO STORE THE HEX CHARS.
;ALGORITHM : EXTRACT LOWEST 4 BITS OF AX, CON-
;VERT THEM IN HEX DIGIT, SHIFT RIGHT AX 4 BITS, 
;REPEAT THE PROCESS 3 MORE TIMES (BECAUSE AX
;CONTAINS 4 GROUPS OF 4 BITS, EACH GROUP IS ONE
;HEX CHAR.

number2hex proc
  add  si, 3
n2h:     
;GET 4 BITS FROM AX.
  mov  bl, al        ;GET LOWEST 4 BITS OF AX.
  and  bl, 00001111b ;ISOLATE LOWER 4 BITS.
  shr  ax, 4         ;GET RID OF THOSE 4 BITS.
;CONVERT 4 BITS TO HEX CHAR.  
  cmp  bl, 9
  ja   letter                                 
  add  bl, 48        ;CONVERT TO DIGIT 0..9.  
  jmp  skip_letter
letter:
  add  bl, 55        ;CONVERT TO LETTER A..F.  
skip_letter:
  mov  [si], bl
  dec  si
  cmp  ax, 0
  jne  n2h

  ret
number2hex endp  

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

end
相关问题