8086 как поменять байт в регистре - PullRequest
0 голосов
/ 21 декабря 2018

Как можно изменить значение регистра на уровне байтов?

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.

Ответы [ 3 ]

0 голосов
/ 22 декабря 2018

Для обращения битов в байте используйте таблицу поиска.Для обращения битов в слове используйте таблицу поиска, чтобы инвертировать младшие 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), вы можете использовать справочную таблицу, чтобы сделать это быстро.

0 голосов
/ 23 декабря 2018

В то время как другие ответы дают вам прямое решение вашей проблемы, я хотел бы написать кое-что о теории, потому что я думаю, что она поможет вам в следующий раз:

Как вы уже написали,десятичное число 1234 записывается как 4D2 в шестнадцатеричной системе, а 4321 записывается как 10E1.

Это означает, что операция «обращение числа» приводит к различным результатам в разных системах счисления:

в десятичном видеСистема «Возврат» 1234 приводит к 4321. В шестнадцатеричной системе «Возврат» 4D2 приводит к 2D4.Используя фиксированную длину из 4 шестнадцатеричных цифр (16-битных регистров!), Однако «возврат» 04D2 приведет к 2D40 ...

Если какая-то операция работает только в определенной базе (*), вы должны учитыватьследующее:

Используя компьютер, работающий с байтами, вы можете легко выполнять операции в base-256: xchg bh,bl "вернет" две цифры числа в системе base-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

(*) Операция, которую вы хотите выполнить, заключается не в «возврате числа», а в «возврате десятичного числа».

0 голосов
/ 22 декабря 2018

Мне тоже непонятно по вашему вопросу.вы используете операционную систему 8086 и говорите об обращении байта, а затем продолжаете, подразумевая, что вы хотите изменить (16-битное) число, например 1234.

У меня нет EMU8086, установленного в настоящее время на моем x64 nix, ноСледующие коды могут помочь понять один из способов достижения ваших целей:

; ----------------------------------------------------------------------------
; foo.asm
; 
; build on nix with nasm:
;   nasm -f elf foo.asm && gcc -m32 -o dofoos foo.o
;
; ----------------------------------------------------------------------------  

extern  printf

SECTION .data   
fmt: db "ecx:%d", 10, 0  


SECTION .text                   

global main


main:    

mov   ax, 3121   ;initialize input register
mov   bx, 10     ;base10 shift multiplier
xor   ecx, ecx   ;zero-bomb output register (i is on x64 so nuke ecx to avoid garbage)

ADINFINITUM:
xor   dx, dx     ;zero bomb div remainder register 
div   bx         ;div puts quotient in ax and remainder in dx
push  ax         ;push div results to stack to free up registers
push  dx         ;push div results to stack to free up registers
mov   ax, cx     ;reset ax with current output value
mul   bx         ;base10 left-shift current output. result goes to ax 
pop   dx         ;pop back current remainder
add   ax, dx     ;add current remainder to current output
mov   cx, ax     ;update cx with current output
pop   ax         ;pop back current quotient
cmp   ax, 0      ;repeat unless current quotient is zero 
jnz   ADINFINITUM


push  ecx        ;display contents of cx output register
push  fmt
call  printf
add   esp, 8
ret    

Если вы хотите просто перевернуть байт, то это немного отличается.Нечто подобное может помочь:

; ----------------------------------------------------------------------------
; foo.asm
; 
; build on nix with nasm:
;   nasm -f elf foo.asm && gcc -m32 -o dofoos foo.o
;
; ----------------------------------------------------------------------------  

extern  printf

SECTION .data   
fmt: db "ecx:%d", 10, 0  


SECTION .text                   

global main


main:    

mov   al, 13     ;initialize input register
mov   bl, 10     ;base10 shift multiplier
xor   ecx, ecx   ;zero-bomb output register (i is on x64 so nuke ecx to avoid garbage)

ADINFINITUM:
xor   ah, ah     ;zero bomb div remainder register 
div   bl         ;div puts 8bit quotient in al and remainder in ah
push  ax         ;push div results to stack to free up registers
mov   al, cl     ;reset al with current output value
mul   bl         ;base10 left-shift current output. result goes to ax 
pop   dx         ;pop back div results  
add   al, dh     ;add current remainder to current output
mov   cl, al     ;update cx with current output
mov   al, dl     ;reset al with current quotient
cmp   dl, 0      ;repeat unless current quotient is zero 
jnz   ADINFINITUM


push  ecx         ;display contents of ecx output register
push  fmt
call  printf
add   esp, 8
ret    
...