简体   繁体   English

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

[英]How can I convert a 4 digit hex number into Two's complement with neg

How can I convert a 4 digit hex number into Two's complement with neg 如何将4位十六进制数字转换为带负数的二进制补码

I want to input a 4 digit hex number, if it is negative, it will be switched to positive, and then I want to use two complement technique to find the result. 我想输入一个4位数的十六进制数,如果它为负数,它将切换为正数,然后我想使用两个补码技术来查找结果。

For example, if I input F520h , the output will be -F520h = 0AE0h 例如,如果我输入F520h ,则输出将为-F520h = 0AE0h

The problem is, when I input the 4 digits, it is in ASCII, how can I determine if it is a digit or a number without checking 0-9, AF.. 问题是,当我输入4位数字时,它是ASCII码,如何在不检查0-9 AF的情况下确定它是数字还是数字。

Things you should understand to be prepared to design code for this: 准备为此设计代码时应了解的事项:

How input "string" is stored in memory ( "F520h" are at least 5 bytes, maybe more, with some terminator value appended after) - depends on the method how you read input from user, consult the used API documentation. 输入“字符串”如何存储在内存中( "F520h"至少为5个字节,也许更多,并在后面附加一些终止符)-取决于您如何从用户读取输入的方法,请查阅所用的API文档。

What is ASCII table, ie how to convert single character [0-9A-Fa-f] to value 0 - 15 . 什么是ASCII表,即如何将单个字符转换[0-9A-Fa-f]珍惜0 - 15 Hint: if you examine closely encoding of 'a' and 'A' , you may find out way how to convert them into value 10 with one sub (or add ) and and (working for other letters too). 提示:如果您仔细检查'a''A'编码,您可能会发现如何使用一个sub (或add )和and (也适用于其他字母)将它们转换为值10的方法。 Turning character '0' into value 0 is even easier. 将字符'0'转换为值0更容易。

How to build 16 bit value from four 0-15 (4 bit) values. 如何从四个0-15 (4位)值构建16位值。 Hint: 4 * 4 bits = 16 bits, so this can be achieved by bit manipulating operations only, without any multiply/divide math involved. 提示:4 * 4位= 16位,因此只能通过位操作来实现,而无需涉及任何乘法/除法数学运算。

How to test if value is negative (probably the CPU already has "SF" flag set for you after that 16b value build last instruction, so all you need is js instruction then. 如何测试值是否为负(在那条16b值生成最后一条指令之后,CPU可能已经为您设置了“ SF”标志,因此,您所需要的只是js指令

How to negate the 16b value... x86 has neg instruction . 如何取反16b值... x86具有neg指令

How to output the resulting number: 如何输出结果数:

Will require you to break 16 bit value into four 4b values (again bitwise operations should be enough, like and and shr instructions doing the most of the job). 将需要您将16位值分成四个4b值(再次按位运算就足够了,例如andshr指令完成了大部分工作)。

Turn those 0 - 15 4 bit values values back into ASCII characters (so again understanding ASCII encoding should help). 把这些0 - 15 4位值值回ASCII字符(如此反复理解ASCII编码应该帮助)。

Create output string from those characters in required format for your output API call (will probably require some terminator value at end, or exact length of string to output). 从这些字符中以输出API调用所需的格式创建输出字符串(可能需要在末尾添加一些终止符值,或要输出的确切字符串长度)。


If you don't know anything about Assembly, this may be quite complex to write correctly in form of instructions and will take few days probably. 如果您对汇编一无所知,以指令的形式正确编写可能会很复杂,可能需要几天的时间。

Although on algorithm side it's quite simple (the complexity is hidden more in the amount of work to be done), I would expect you can "see" the math behind each of the points I listed. 尽管在算法方面非常简单(复杂性更多地隐藏在要做的工作中),但我希望您可以“看到”我列出的每个要点后面的数学知识。 And those steps are listed in order somewhat related to the algorithm I have on my mind. 这些步骤是按顺序列出的,这些顺序与我想到的算法有些相关。

Make sure you have first the idea how to calculate the output from the input on the theoretical level (algorithm), describe that in very simple steps involving only basic numerical operations (check overview of 8086 CPU ASM instructions to get idea what kind of operation is "basic" enough for the CPU and how it can manipulate numbers/bits). 确保首先了解如何在理论水平(算法)上从输入中计算输出,并描述仅涉及基本数值运算的非常简单的步骤(查看8086 CPU ASM指令概述以了解哪种运算是对于CPU以及它如何处理数字/位足够“基本”。

Then you can focus how to achieve each step with few x86 instructions. 然后,您可以集中精力用很少的x86指令来实现每个步骤。

There're also many questions on stack overflow regarding particular steps you will encounter, like how to print hexadecimal value, etc, so you may check those for ideas (just make sure the target platform of answer is same as yours, or understand the idea behind the answer, so you can write it on your own). 关于堆栈溢出,还会遇到很多与您将要遇到的特定步骤有关的问题,例如如何打印十六进制值等,因此您可以检查这些想法(只是确保答案的目标平台与您的想法相同,或者理解该想法)在答案后面,因此您可以自己编写)。


EDIT: BTW, this task has another major way how to solve it, as you only need to negate ASCII encoded hexadecimal number, you don't even need it to convert it to numerical value, it's possible to patch the ASCII characters themselves to produce the neg result. 编辑:顺便说一句,此任务还有另一种解决方法,因为您只需要取反ASCII编码的十六进制数,甚至不需要将其转换为数值,就可以修补ASCII字符本身以产生neg结果。 Although neg is a bit tricky (but doable). 尽管neg有点棘手(但可行)。 I recall doing this for xor (in C++, but this compiles almost 1:1 to ASM instructions), when the high performance was required and conversion to number and back to string was too costly. 我记得在xor这样做(在C ++中,但是这几乎将1:1编译为ASM指令),这时需要高性能,并且转换成数字然后转换成字符串的代价太高了。

But if you are trying to learn Assembly, it's probably better to do it in the first way, so you can learn and understand all those conversions and how hexadecimal numbers can be converted between string<->value in assembly. 但是,如果您要学习汇编语言,最好以第一种方式进行学习,这样您就可以学习和理解所有这些转换,以及如何在汇编语言的string <->值之间转换十六进制数字。

Next code does the job : user enters a hex number (up to 4 digits, example "F520") as string, converts the string to number in ax , neg is applied to ax , the result is converted back to hex string and displayed (example "0AE0"), you just copy-paste it and run it : 接下来的代码完成该工作:用户输入一个十六进制数字(最多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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM