[英]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值(再次按位运算就足够了,例如
and
和shr
指令完成了大部分工作)。
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.