如何在字节级别反转寄存器值?
mov al,12 -----> how can i reverse al value
to 21
这是我尝试过的:
mov bx,4321 ;i want to make bx 1234
mov cl,04 ;cl for rotation value
xchg bh,bl ; now bx will 2143
mov al,bh ;moving 21 to al
rol al,cl ; rotate al 4 times to left now al is 12`
mov bh,al ; bh is 12 setuped ,time for bl
;---------------------------
mov al,bl ;moving lower byte 43 to al
rol al,cl ; rotate 4 times to left now al will 34
mov bl,al ; moving 34 to bl
现在
bx
必须包含颠倒的数字1234;问题是数字是十六进制的,即 10e1h 或 4321。
当我反转时,它是1e01h,但这个值并不表示1234。
1234 是 04d2。我得到的值是 7681d。
虽然其他答案为您提供了问题的直接解决方案,但我想写一些有关该理论的内容,因为我认为它下次会对您有所帮助:
正如您已经写过的,十进制数 1234 在十六进制系统中写为 4D2,4321 写为 10E1。
这意味着“恢复数字”操作在不同的数字系统中会导致不同的结果:
在十进制系统中,“还原”1234 会生成 4321。在十六进制系统中,“还原”4D2 会生成 2D4。使用 4 个十六进制数字的固定长度(16 位寄存器!),但是“恢复”04D2 将导致 2D40...
如果某些操作只能在某个基数(*)中起作用,则必须考虑以下事项:
使用使用字节的计算机,您可以轻松地执行以 256 为基数的运算:
xchg bh,bl
将“恢复”以 256 为基数的系统中数字的两位数。
可以使用移位和旋转以 2^N 为基数(例如二进制、八进制或十六进制)执行运算。
但是,在其他基数(例如十进制)上进行运算时,您将需要计算个位数,执行运算并根据数字计算(二进制)数。
要恢复十进制数,以下伪代码可能有效:
A = input (here: 1234)
B = 0
mainLoop:
digit = A mod 10 (get the right digit of A)
A = A/10 (remove the right digit from A)
B = 10*B + digit (append the digit to B)
if A>0: jump to mainLoop
在汇编程序中,代码可能如下所示:
mov ax,1234 ; ax = "A" in the pseudo-code
mov cx,0 ; cx = "B" in the pseudo-code
mov bx,10 ; The base we are working in
mainLoop:
xchg ax,cx ; "mul" can only work with ax
mul bx ; Results: ax = "10*B"
; dx = overflow (typically 0)
xchg ax,cx ; Change ax and cx back: cx="10*B"
mov dx,0 ; Prepare dx for "div"
div bx ; Perform division and modulo
; Result:
; ax = "A/10"
; dx = "A MOD 10" = "digit"
add cx,dx ; "B = 10*B+digit"
cmp ax,0
ja mainLoop
; Here cx will contain the "reverted" number
(*) 您要执行的操作不是“恢复数字”而是“恢复十进制数字”。
要反转字节中的位,请使用查找表。要反转字中的位,请使用查找表反转最低 8 位,然后
rol ax,8
,然后使用查找表反转其他 8 位。
要反转字节中的(4 位)半字节,请使用
rol al,4
。要反转单词中的半字节,请使用 rol al,4; rol ax,8; rol al,4
。
用于反转字节或字中的十进制数字;不。相反,更改打印十进制数字的代码。原因是从整数(例如值 1234)到字符串(例如字符“1234”)的转换通常会以相反的顺序生成字符,并且必须执行额外的工作来反转字符;因此,“print_reversed_decimal()”会做更少的工作(并且以其他方式反转数字,然后在打印时再次反转它,这会增加两倍的工作量!)。或者,您可以使用 BCD(其中每个半字节包含一个十进制数字)。在这种情况下,您可以使用“反向半字节”方法来反转十进制数字,并且打印之后的数字变得便宜得多(移位和掩码而不是除法和模数)。
请注意,反转整数中的小数位的数学类似于:
k = 10000000;
result = 0;
while(value > 0) {
digit = input % 10;
result += digit * k;
input /= 10;
k /= 10;
}
但是,您必须首先确定
k
的正确值(这取决于是否忽略前导零或反转 - 例如,如果 012 变为 210 或 021)。另请注意,这是昂贵的(循环内的除法、模数和乘法),这就是为什么您要尽一切可能避免这样做。当然,如果数字范围足够小(例如仅从 000 到 199 的值),那么您可以使用查找表来快速完成此操作。