6502 ассемблерный двоичный код в bcd - возможно ли это на x86?

У меня есть несколько вопросов по этому коду:

; Convert an 16 bit binary value to BCD
;
; This function converts a 16 bit binary value into a 24 bit BCD. It
; works by transferring one bit a time from the source and adding it
; into a BCD value that is being doubled on each iteration. As all the
; arithmetic is being done in BCD the result is a binary to decimal
; conversion. All conversions take 915 clock cycles.
;
; See BINBCD8 for more details of its operation.
;
; Andrew Jacobs, 28-Feb-2004

        .ORG $0200

BINBCD16:   SED     ; Switch to decimal mode
        LDA #0      ; Ensure the result is clear
        STA BCD+0
        STA BCD+1
        STA BCD+2
        LDX #16     ; The number of source bits

CNVBIT:     ASL BIN+0   ; Shift out one bit
        ROL BIN+1
        LDA BCD+0   ; And add into result
        ADC BCD+0
        STA BCD+0
        LDA BCD+1   ; propagating any carry
        ADC BCD+1
        STA BCD+1
        LDA BCD+2   ; ... thru whole result
        ADC BCD+2
        STA BCD+2
        DEX     ; And repeat for next bit
        BNE CNVBIT
        CLD     ; Back to binary

        BRK     ; All Done.

; A test value to be converted

        .ORG $0300

BIN     .DW  12345
BCD     .DS  3

с этого сайта.

Я не понимаю, что именно делает эта строка:

ROL BIN+1

Выполняется ли сдвиг вправо на втором байте BIN? Если да, то что именно находится в этом байте?

Также можно ли написать что-нибудь подобное для x86? Можно ли использовать BCD, чтобы распечатать число в десятичном формате с помощью x86 каким-то элегантным способом? Или лучше придерживаться деления на 10? Я кое-что знаю об инструкциях AAA, AAM, но не знаю, действительно ли они полезны.


person Community    schedule 23.12.2020    source источник
comment
ROL = повернуть влево. Так что это не сдвиг и не правильно: D Но да, это второй байт. _2 _ + _ 3_ вместе сдвигают 16-битное число в BIN и BIN+1. ROL используется для преобразования старшего бита младшего байта в младший бит старшего байта.   -  person Jester    schedule 24.12.2020
comment
Обратите внимание, что этот код использует упакованный BCD, поэтому на x86 вам нужно будет использовать DAA, а не AAA инструкцию. Кроме того, файлы BCD устарели и недоступны в 64-битном режиме.   -  person Jester    schedule 24.12.2020
comment
Упакованный BCD не очень подходит для печати, так что вы можете все же использовать распакованный :)   -  person Jester    schedule 24.12.2020
comment
О, хорошо, спасибо. Я часами искал эти инструкции BCD для x86, но я не мог понять их, чтобы «центрировать» этот код для 6502 на x86.   -  person    schedule 24.12.2020
comment
Я бы, наверное, сделал это делением на 10, это кажется наиболее естественным способом, но в моем задании написано «использование преобразования BCD ...», чему я не очень доволен;)   -  person    schedule 24.12.2020
comment
Непонятно, что они подразумевают под преобразованием в двоично-десятичный код. Это может означать просто реализовать преобразование BCD самостоятельно, например используя div. (Или эффективно использовать imul с мультипликативным обратным преобразованием, как в этом алгоритме преобразования целого числа в ASCII (сборка x86) - он даже сдвигает десятичные цифры ASCII в регистр; вы можете сделать это для упакованного или распакованного BCD без добавления '0'. Деление на 10 до 6 десятичных цифр (особенно с использованием обратного умножения) будет быстрее на современных x86, чем порт Jester ваш код 6502.   -  person Peter Cordes    schedule 24.12.2020


Ответы (1)


ROL = повернуть влево. Да, это второй байт. _2 _ + _ 3_ вместе сдвигают 16-битное число в BIN и BIN+1 влево на один бит. ROL используется для распространения MSB младшего байта в LSB старшего байта, в то время как MSB старшего байта перемещается во флаг переноса, который используется инструкцией ADC.

Обратите внимание, что этот код использует упакованный BCD, поэтому на x86 вам нужно использовать DAA, а не инструкцию AAA. Кроме того, файлы BCD устарели и недоступны в 64-битном режиме. Тем не менее, здесь эквивалентный код x86 с добавленным преобразованием текста и печатью. Ассемблер GNU at & t, 32-битный Linux:

.globl main
main:
    sub $8, %esp
    mov $12345, %edx
    mov $16, %ecx
repeat:
    shl %dx
    mov bcd, %al
    adc %al, %al
    daa
    mov %al, bcd
    mov bcd+1, %al
    adc %al, %al
    daa
    mov %al, bcd+1
    mov bcd+2, %al
    adc %al, %al
    daa
    mov %al, bcd+2
    dec %ecx
    jnz repeat

# print
    lea bcd+2, %esi
    lea txt, %edi
    call unpack
    call unpack
    call unpack
    push $txt
    call puts
    call exit

unpack:
    mov (%esi), %al
    dec %esi
    mov %al, %ah
    shr $4, %al
    and $15, %ah
    add $0x3030, %ax
    stosw
    ret

.lcomm bcd, 3
.lcomm txt, 7

Вышеупомянутое не является рекомендуемым способом сделать общий int-to-string, это просто перевод кода 6502 в вопросе.

person Jester    schedule 23.12.2020
comment
Вероятно, было бы быстрее использовать быстрый множитель x86 для реализации деления на 10 (например, алгоритм преобразования целого числа в ASCII (сборка x86) Даже результаты сдвигают в регистр, можно было бы адаптировать к BCD). Или даже инструкция div на современной x86, где она не так медленна для десятичных цифр до 6 против 16 итераций этого. Транслитерировать это в некоторой степени интересно, но вы должны хотя бы упомянуть, что это не единственный способ получить десятичные цифры и, вероятно, медленный. - person Peter Cordes; 24.12.2020
comment
И IDK, почему вы использовали медленную loop инструкцию или использовали lea txt, %edi вместо сохранения байта с mov $txt, %edi. Кроме того, загрузка одного байта в наши дни обычно лучше всего выполнять с movzbl (%esi), %eax, чтобы сломать ложную зависимость от старого значения. - person Peter Cordes; 24.12.2020
comment
Да, это была просто транслитерация, насколько я понял вопрос. Хорошо, исходный код также использовал dex; bne, давайте удалим loop :) lea ... силу привычки, я хотел использовать относительный рип, но, конечно, это 32-битный код. Не то чтобы я даже думал об оптимизации по размеру или скорости ... больше похоже на удобочитаемость. - person Jester; 24.12.2020