Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Assembler > конвертация типов


Автор: cupoma58 04.05.18, 09:49
Привет. Пытаюсь создать простой калькулятор (masm32). Знак "-" не вводится. Основной код готов, осталась конвертация:
...
call GetWindowText ---> str с дисплея в eax
...
call str_dec_hex_bin_proc
...
call bin_hex_dec_str_proc
...
call SetWindowText ---> str на дисплей
...
Возится с процедурами - лень. Подскажите - где подсмотреть готовые или, хотя-бы, по частям.
-----------------------------
Подсказали две функции: GetDlgItemInt и SetDlgItemInt
Правильно-ли я понял из описания:
Eсли, при получении набранного на дисплее числа, вместо GetWindowText использовать GetDlgItemInt,
то в ЕАХ уйдёт "bin" ?
A, при добавлении на дисплей результата операции, вместо SetWinlowText использовать SetDlgItemInt,
то в ЕАХ уйдёт "str" ?
Если в общем: str --> GetWindowText --> bin --> SetDlgItemInt --> str ?
----------------------------
А главное - учитывают-ли эти функции символ "точка" как признак дробнoсти вводимого числа ?

Автор: Qraizer 04.05.18, 12:45
GetDlgIntemInt() сразу возвращает число, при этом она учитывает "-" впереди, если он есть. SetDlgIntemInt() возвращает просто признак успеха. А что ей ещё возвращать-то? Но надо правильно указать последний параметр, иначе отрицательные числа будут восприняты неверно (или наоборот). Обе функции не работают с плавающей точкой, т.к. функции ОСовые и должны обслуживать любые программы, а плавающая точка сильно зависит от используемого в программах языка программирования.
Готовые функции для преобразования несложно нагуглить, но интереснее написать. Там ничего сложного. Пробуй, поможем.

Автор: Jin X 05.05.18, 07:05
Для преобразования чисел в строки можно использовать wsprintf из USER32.DLL (но он не понимает float - %f) или sprintf из MSVCRT.DLL (crt_sprintf в MSVCRT.INC для MASM32, %f понимает).
Из строк в числа – atoi/atoi64/atol/atoll (integer), atof (float). См. MSDN.

В MASM32 есть библиотека MASM32.LIB (MASM32.INC), там есть функции типа atodw/a2dw (для беззнаковых), atol (знаковые), atofp, fptoa/fptoa2 (float).
Исходники в папке m32lib.

Автор: cupoma58 15.05.18, 09:55
Цитата Jin X @

Благодарю, попробую.

Автор: cupoma58 18.07.18, 08:13
Доделал графику арифмометра, добрался до преобразования типов: строка <--> дес.число <--> дв.код. Обнаружил подсказку (Р.Марек)и
переделал её для целых положительных чисел (дес.число --> строка):
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    ;преобразуем число в строку:  
    dec2asc proc              ;выход: заполненный ascbuf
      pushad                  ;сохраняем все регистры общего назначения
      mov  ebx,0Ah            ;EBX = основание системы счисления
      mov  eax,bincod         ;EAX = число
      lea  edi,ascbuf         ;EDI = указатель на строку-результат
      xor  esi,esi            ;ESI = 0 - счетчик цифр в стеке
      conv:
        xor  edx,edx          ;сюда - остаток от деления - цифра
        div  ebx              ;делим ЕАХ на ЕВХ, частное в ЕАХ, остаток в EDX
        add  dl,"0"           ;преобразуем остаток в ASCII-символ и...
        push edx              ;...запихиваем в стек
        inc  esi              ;увеличиваем счётчик цифр в стеке
        test eax,eax          ;ЕАХ = 0 ?
        jnz  conv             ;если - нет, продолжаем
        cld                   ;сбрасываем флаг направления DF, запись вперёд
      write:
        pop  eax              ;выталкиваем цифры из стека                  
        stosb                 ;записываем byte из AL в буфер по адресу ES:EDI
        dec  esi              ;уменьшаем к-во оставшихся цифр
        test esi,esi          ;ESI=0 ?
        jnz  write            ;если - нет, переходим к следующей цифре
        mov  byte ptr [edi],0 ;заканчиваем строку 0-вым байтом
        popad
        ret
    dec2asc endp

Есть одна непонятность: ASCII-символы накапливаются в EDX и сохраняются в стеке (для разворота). Почему их достают из EAX ? Судя по
команде "stosb" - это не опечатка.
И ещё один момент: поскольку числа целые, в арифметике я использую FIxxx, например:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
      …
      fild  var1
      fild  var2
      fiadd(fisub,fimul,fidiv)  ;error A2070: invalid instruction operands"
      fistp bincod
      ...

Чем моему компилятору (masm32 v.11) не угодили эти команды ?

Автор: Jin X 18.07.18, 19:20
Цитата cupoma58 @
Есть одна непонятность: ASCII-символы накапливаются в EDX и сохраняются в стеке (для разворота). Почему их достают из EAX ?
Их достают не из EAX, а в EAX.
Сохранили в стек, взяв из EDX, а из стека извлекли уже в EAX.
Можно сделать так:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    pop edx
    mov al,dl
но какой смысл писать 2 инструкции, когда можно обойтись одной?
Регистр в инструкции pop необязательно должен соответствовать тому, что был в push.
Иногда push+pop используется как замена mov. К примеру:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    push [eax]
    pop [edx]  ; [edx] = [eax], сделать mov [edx],[eax] нельзя
или
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    push 0
    pop ds  ; ds = 0, сделать mov ds,0 нельзя


Добавлено
Цитата cupoma58 @
Чем моему компилятору (masm32 v.11) не угодили эти команды ?
Написано, что неверно заданы операнды. А где эти операнды?
Полностью строку пришлите, как вы их используете.
Если же вы загружаете 2 числа через fild, а потом хотите их сложить через fiadd, то так не делается. При загрузке (в т.ч. через fild) числа преобразуются в вещественные, так что складывать их нужно через faddp, как и любые другие вещественные числа. Только какой смысл использовать FPU, когда можно обойтись целочисленной арифметикой (mov, add)?
А fild используется так:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    fild var1  ; загружаем целое var1 в st(0) (но оно всё равно преобразуется в вещественное)
    fiadd var2  ; добавляем к st(0) целое число var2 (оно предварительно преобразуется внутри процессора в вещественное)
    fistp result  ; выводим целый результат в result

Автор: cupoma58 12.09.18, 07:30
Цитата Jin X @
Цитата cupoma58 @
Есть одна непонятность: ASCII-символы накапливаются в EDX и сохраняются в стеке (для разворота). Почему их достают из EAX ?
Их достают не из EAX, а в EAX.
Сохранили в стек, взяв из EDX, а из стека извлекли уже в EAX.
Можно сделать так:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    pop edx
    mov al,dl
но какой смысл писать 2 инструкции, когда можно обойтись одной?
Регистр в инструкции pop необязательно должен соответствовать тому, что был в push.
Иногда push+pop используется как замена mov. К примеру:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    push [eax]
    pop [edx]  ; [edx] = [eax], сделать mov [edx],[eax] нельзя
или
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    push 0
    pop ds  ; ds = 0, сделать mov ds,0 нельзя


Добавлено
Цитата cupoma58 @
Чем моему компилятору (masm32 v.11) не угодили эти команды ?
Написано, что неверно заданы операнды. А где эти операнды?
Полностью строку пришлите, как вы их используете.
Если же вы загружаете 2 числа через fild, а потом хотите их сложить через fiadd, то так не делается. При загрузке (в т.ч. через fild) числа преобразуются в вещественные, так что складывать их нужно через faddp, как и любые другие вещественные числа. Только какой смысл использовать FPU, когда можно обойтись целочисленной арифметикой (mov, add)?
А fild используется так:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    fild var1  ; загружаем целое var1 в st(0) (но оно всё равно преобразуется в вещественное)
    fiadd var2  ; добавляем к st(0) целое число var2 (оно предварительно преобразуется внутри процессора в вещественное)
    fistp result  ; выводим целый результат в result

Тема закрыта, арифмометр заработал (cupoma58.ru/assembler.html)
:victory:

Автор: Jin X 12.09.18, 14:25
cupoma58, поздравляю!
p.s. Пожалуйста, не цитируйте такие большие блоки текста – это не несёт смысловой нагрузки, а только загромождает тему.

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)