Сдвиг языка ассемблера на перенос флагов

В настоящее время у меня есть задание, в котором я должен кодировать на языке ассемблера, где вы вводите пользовательский ввод, чтобы получить 4-значное шестнадцатеричное значение и преобразовать его в двоичное, а затем, после того, как вы получите двоичное значение, вы должны преобразовать его в день месяца и год, где первые 7 цифр — год, следующие четыре — месяц, а последние 5 — день.

У меня все преобразовано в двоичный формат, и я знаю, как преобразовать его из двоичного в обычные целые значения года, месяца и дня. Когда я запускаю свой код, вывод равен 0/0/0. Я не уверен, то ли это, где я испортил свое переключение или что-то еще. Не могли бы вы, ребята, взглянуть и дать мне информацию о том, где исправить? В коде, который я вставляю, я добавляю только calcYear и полагаю, что могу понять это, а затем работать над остальными оттуда.

Мой код:

firstLine:

    call crlf
    mov si, offset programOne
    mov cx, programOneLen
    call putStrng       ;displays 'Program by Joe Remaklus'

    call crlf
    call crlf

    call inputVal   ;prompt for hex input
    call putBin ;display the value in AX as binary
    call crlf
    call calcYear   ;display the year of the first 7 binary digits.
    mov si, offset slash
    mov cx, slashLen
    call putStrng
    call calcMonth  ;display the month of the next 4 binary digits.
    mov si, offset slash
    mov cx, slashLen
    call putStrng
    call calcDay    ;display the day of the next 5 binary digits.
    call crlf

    call inputVal
    call putBin






    mov ah,04c
    int 021




prompt db 'Enter a 4-digit hex value'

lenPrompt = $-prompt


inputVal:

    push si, cx

    mov  si, offset prompt

    mov  cx, lenPrompt

    call putStrng

    call crlf

    call getHex

    call crlf

    pop  cx, si

    ret
;---------------------------------------------------------------

putBin:

    push ax, cx, dx

    mov  cx, 16     ;number of bits to display

  putBinLoopTop:

    mov  dl, '0'        ;assume bit to display is zero

    shl  ax, 1      ;shift bit to display into Carry Flag

    jnc  putBinSkipInc  ;if the top bit was zero skip the inc

    inc  dl         ;else inc DL to '1'

  putBinSkipInc:

    call putChar        ;display the character in DL

    loop putBinLoopTop  ;continue until 16 bits are displayed

    pop  dx, cx, ax

    ret
;---------------------------------------------------------------

calcYear:

    mov year, 0

    mov si, 0

    shl ax, 1
    adc si, 0
    iMul onetwoeight
    add year, si
    mov si, 0 

    shl ax, 1
    adc si, 0
    iMul sixfour
    add year, si
    mov si, 0

    shl ax, 1
    adc si, 0
    iMul threetwo
    add year, si
    mov si, 0

    shl ax, 1
    adc si, 0
    iMul sixteen
    add year, si
    mov si, 0

    shl ax, 1
    adc si, 0
    iMul eight
    add year, si
    mov si, 0


    shl ax, 1
    adc si, 0
    iMul four
    add year, si
    mov si, 0


    shl ax, 1
    adc si, 0
    iMul two
    add year, si
    mov si, 0


    shl ax, 1
    adc si, 0
    iMul one
    add year, si
    mov si, year
    add si, 1980
    call putPos
ret

person jbr012    schedule 28.04.2016    source источник
comment
Вы выполнили это в отладчике, чтобы убедиться, что значения в регистрах соответствуют вашим ожиданиям? Вы правы, что shl ax / adc si, 0 эквивалентно тестированию бита на топоре, а затем использованию setcc. (например, xor dx,dx / bt ax, 3 / setc dl, за исключением того, что это не изменяет ax) Я совсем не уверен, что ваши imul имеют смысл. Может быть, это действительно окольный способ сделать что-то, но я не понял, что. Вы же знаете, что умножение на степень двойки — это то же самое, что сдвиг, верно? Кроме того, вы можете все время хранить year в si вместо того, чтобы все время использовать место назначения в памяти.   -  person Peter Cordes    schedule 28.04.2016
comment
понижено из-за отсутствия комментариев в коде или описания того, какой именно алгоритм предполагается реализовать в год. Для меня это выглядит как какое-то странное добавление битов (popcnt). Также за то, что у вас нет минимального примера, который просто демонстрирует проблему, с которой вы столкнулись. Это все еще много кода. Если вы улучшите вопрос, оставьте ответ, и я могу удалить свой отрицательный голос.   -  person Peter Cordes    schedule 28.04.2016
comment
Нет. Используйте отладчик, чтобы определить, где ваш код работает неправильно, и если вы не видите, почему происходит это конкретное поведение, спросите еще раз, указав что-то более конкретное, чем ... введите, где исправить.   -  person David Hoelzer    schedule 28.04.2016


Ответы (1)


Если я вас правильно понял, при вводе calcYear ваш "топор" выглядит в двоичном виде так: гггг гггг ммммд дддд

И вы хотите извлечь значения обратно в обычные числа. Я думаю, что могу понять вашу идею «calcYear», но мне жаль, что я не потрудился полностью понять ее и исправить. Если вам все еще любопытно, просто используйте отладчик, чтобы выполнить пошагово каждую инструкцию и посмотреть, где она идет на юг.

Вместо этого я покажу вам, как думать об этой проблеме по-другому.

Давайте попробуем покопаться и понять это:

    ; ax is encoded as this: yyyy yyym mmmd dddd
    push ax
    push ax ; store the encoded value at stack twice
    ; extract "day" value
    and ax,01Fh  ;only "d" bits will survive
    mov [day],ax
    ; extract "month" value
    pop ax ; restore encoded input
    shr ax,5 ; shift ax by number of "d" bits
    and ax,0Fh ; only shifted "m" bits
    mov [month],ax
    ; extract "year" value
    pop ax ; restore encoded input
    shr ax,5+4 ; shift ax by number of "d" and "m" bits
    ; no need to "and", as "shr" did fill upper bits by zeroes
    add ax,1980 ; so "0" encoded year is 1980? (deducted from OP source)
    mov [year],ax
    ret

Надеюсь, это даст вам новые идеи о том, как работать с определенными битами числа. Имейте в виду, что and/or хороши для того, чтобы скрыть то, что вас интересует, а shr/sar/sal/shl/ror/rol/rcr/... хороши, чтобы поместить их в нужное место. xor можно использовать для некоторого исправления результата (при необходимости), test похож на and, но получает только обновление регистра флагов, а затем есть еще несколько бит-ориентированных инструкций x386+ (или 486?), которые несколько "продвинуты" и могут сэкономить у вас есть 2-3 комбинации инструкций из тех основ, о которых я упоминал ранее. Таким образом, вы можете смело игнорировать их, если вы полностью понимаете эти основные и можете сгибать с ними все, что хотите.

person Ped7g    schedule 28.04.2016
comment
И в случае, если вам интересно, как я думал об этой проблеме... к сожалению, я показал вам только половину магии, это самая первая строка: ; ax is encoded as this: yyyy yyym mmmd dddd = 1) убедитесь, что вы понимаете, какие у вас входные данные. Скрытая вторая половина магии заключается в том, чтобы 2) полностью осознавать желаемые выходные данные, в этом случае я хотел получить year = 0yyy yyyy, month = 0000 mmmm, day = 000d dddd ... затем я начал думать, как перемещать эти биты и извлекать их, маскируя, чтобы получить желаемый результат . Убедитесь, что вы полностью понимаете цель, а затем найдите алгоритм для ее достижения. - person Ped7g; 28.04.2016
comment
И последнее замечание... если вы студент, вы можете задаться вопросом, почему and ax,01F (почему я использую шестнадцатеричный способ 31)... потому что после многих лет программирования на ASM я почти вижу биты в шестнадцатеричных числах, поэтому, например, AA хороший шаблон 1010 1010 ... Просто имейте в виду, что каждые 4 бита (иногда называемые полубайтами) образуют одну шестнадцатеричную цифру, поэтому вычисление шестнадцатеричного значения из длинного двоичного числа для человека на самом деле проще, чем попытка вычислить десятичное значение, которое включает в себя много умножения и добавления. Поэтому, когда я пишу и регистрирую MASK, и я знаю значение MASK в двоичном формате, я просто пишу его в шестнадцатеричном формате из головы. - person Ped7g; 28.04.2016
comment
Не проголосовал из-за твоего сумасшедшего предложения push ax дважды. Как насчет того, чтобы нажать один раз, а затем просто загрузить вместо poping? Или еще лучше, скопируйте его в другой регистр. В противном случае, довольно хороший ответ, но эти вопросы о дампе кода не добавляют особой ценности SO для будущих читателей. - person Peter Cordes; 28.04.2016
comment
@PeterCordes из любопытства, что такого сумасшедшего в push/pop? Я имею в виду: именно для этого был введен стек (в теории программирования) для хранения временных значений. Конечно, клонирование значения в другой регистр должно быть намного быстрее с точки зрения производительности на текущем процессоре (поскольку оно не требует каких-либо манипуляций с памятью), может быть, даже проще для чтения/понимания в источнике, но... Обратите внимание, мой пример не не загрязнять другие регистры (работает только с ax), что само по себе может быть интересным уроком, а также должно подтолкнуть ученика к большему изучению push. ;) - person Ped7g; 03.05.2016
comment
Мое главное возражение заключается в том, что вы нажимаете дважды вместо push / mov ax, [bp-?] / pop ax. О, я думаю, вы избегали тратить инструкции на кадр стека, а 16-битный не может использовать [sp] ... Тем не менее, я не поклонник стиля кодирования, который избегает использования временных регистров. Полезно узнать о регистрах, сохраняемых вызовами, и о регистрах, затираемых вызовами, которые функции могут использовать для временного хранения. Я должен признать, что ваши дополнительные push также лучше, чем использование адресов памяти повсюду. - person Peter Cordes; 03.05.2016
comment
Я не думаю, что на этот вопрос вообще нужно было отвечать. Это не минимальный пример проблемы, с которой сталкивается ОП, и я не думаю, что она будет иметь большую ценность для будущих читателей SO, поэтому она просто занимает место. Ответы на плохие вопросы только побуждают людей продолжать их задавать. Я также должен признать, что я склонен оставлять комментарии с небольшой помощью, прежде чем голосовать против и голосовать за закрытие. Но полные рабочие решения определенно слишком много для некоторых вопросов. В любом случае, проголосуйте за то, чтобы не тратить инструкции на создание кадра стека. - person Peter Cordes; 03.05.2016
comment
Спасибо за объяснение. Я склонен не слишком часто использовать нотацию [bp-?], так как когда я занимался сборкой Z80 и x86, я делал целые приложения только на ассемблере, не взаимодействуя с другими языками, поэтому я вообще не использовал кадр стека. (и обычно я обрабатывал параметры в регистрах). Кстати, это было безумие, но как-то я не возражал против этого тогда (когда все, что вы знаете, безумно, безумие кажется вам вполне нормальным :) ... потом я выучил несколько языков более высокого уровня, ООП, больше теории и т. д. и вдруг один файл .ASM размером 700 КБ выглядел немного странно). - person Ped7g; 05.05.2016
comment
Кстати, есть целые языки высокого уровня, где стек (и выталкивание/выталкивание значений перед подпрограммами) является основным рабочим столом, эта идея проталкивания значения вперед (и построения входного стека), вероятно, исходит оттуда. Я никогда не писал ничего серьезного на этих языках (четвертая семья?), но изучение их позволяло мне иногда использовать эти идеи. - person Ped7g; 05.05.2016