8086如何反转寄存器中字节的十进制数字

问题描述 投票:0回答:2

如何在字节级别反转寄存器值?

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。

assembly x86-16 masm emu8086
2个回答
4
投票

虽然其他答案为您提供了问题的直接解决方案,但我想写一些有关该理论的内容,因为我认为它下次会对您有所帮助:

正如您已经写过的,十进制数 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

(*) 您要执行的操作不是“恢复数字”而是“恢复十进制数字”。


2
投票

要反转字节中的位,请使用查找表。要反转字中的位,请使用查找表反转最低 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 的值),那么您可以使用查找表来快速完成此操作。

© www.soinside.com 2019 - 2024. All rights reserved.