如何使用neg
将4位十六进制数转换为二进制补码我想输入一个4位十六进制数,如果是负数,它将切换为正数,然后我想用两种补码技术来查找结果。
例如,如果我输入F520h
,则输出将为-F520h = 0AE0h
问题是,当我输入4位数时,它是ASCII格式,如何在不检查0-9,A-F的情况下确定它是数字还是数字。
答案 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-15
和and
指令可以完成大部分工作。
将那些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