Gistrec icon

Asm lab 1 v2

Gistrec | PRO | 10/10/18 02:17:51 AM UTC | 0 ⭐ | 12614 👁️ | Never ⏰ | []
ASM (NASM) |

0 B

|

None

|

0 👍

/

0 👎

.386
.MODEL FLAT, STDCALL
 
 
;#region Прототипы внешних функций
; Внешние функции описываются директивой EXTERN,
; после знака @ указывается общая длина передаваемых параметров,
; после двоеточия указывается тип внешнего объекта – процедура
EXTERN  GetStdHandle@4: PROC ; Позволяет получить дискрипторы ввода и вывода
EXTERN  WriteConsoleA@20: PROC
EXTERN  CharToOemA@8: PROC
EXTERN  ReadConsoleA@20: PROC
EXTERN  ExitProcess@4: PROC; функция выхода из программы
EXTERN  lstrlenA@4: PROC; функция определения длины строки
EXTERN  wsprintfA: PROC; т.к. число параметров функции не фиксировано,
        ; используется соглашение, согласно которому очищает стек вызывающая процедура
;#endregion Прототипы внешних функций
 
.DATA ; сегмент данных
;#region Данные
; выводимая строка, в конце добавлены
; управляющие символы: 13 – возврат каретки, 10 – переход на новую
; строку, 0 – конец строки; с использованием директивы DB
; резервируется массив байтов
WRITE_VALUE DB "Введите число в 16-ти ричной системе: ",13,10,0
WRITE_LENGTH DD ? ; Длина строки
 
; Деректитва DD резервирует память объемом 32 бита (4 байта)
; знак «?» используется для неинициализированных данных
 
FIRST_STRING DB 50 dup (?); Первое число в строковм виде
FIRST_LENGTH DD ? ; Длина первого числа
FIRST_INT DD 0 ; Значение hex строки в dec
 
SECOND_STRING DB 50 dup (?); Второе число
SECOND_LENGTH DD ? ; Длина второго числа
SECOND_INT DD 0 ; Значение hex строки в dec
 
RESULT_INT DD ? ; Результат (dec строка)
 
LENS DD ? ; Буффер для длины строки (для ввода/вывода)
D_IN DD ? ; Дескриптор ввода
D_OUT DD ?; Дескриптор вывода
;#endregion Данные
BUFF DB 50 dup (?)
.CODE; сегмент кода
 
;---------------------------------------------------
; Преобразование QWORD в десятичное число
; Параметры вызова:
; dwHigh - Старшее двойное слово
; dwLow  - Младшее двойное слово
; lpBuff - указатель на буфер-приемник
;---------------------------------------------------
bignum PROC
        pushad                   ; Сохранить все регистры
        mov     edi, OFFSET BUFF     ; Указатель на буфер-приемник
 
        xchg    esi,edx          ; Сохранить старший dword
        mov     ebx,10           ; Основание системы счисления
        xor     ecx,ecx          ; Счетчик десятичных цифр
@bignum_1:
        xchg    eax,esi          ; Расчитать десятичную цифру
        xor     edx,edx
        div     ebx
        xchg    esi,eax
        div     ebx
        or      dl,'0'           ; Преобразовать результат в символ цифры
        push    edx              ; Сохранить цифру в стеке
        inc     ecx              ; Увеличить счетчик цифр
        or      eax,eax          ; Все преобразовали?
        jnz     @bignum_1
@bignum_2:
        pop     eax              ; Записать все цифры из стека в буфер
        stosb
        loop    @bignum_2
        xor     eax,eax          ; Признак окончания строки
        stosb
        popad                    ; Восстановить все регистры
        ret                      ; Ворзврат из процедуры
bignum endp
 
;#region HEX_SYMBOL_TO_DEC
; Получает из HEX символа DEC число
; Входные данные:
;    1. Регистр BL
; Выходные данные:
;    1. Регистр BL
HEX_SYMBOL_TO_DEC PROC
    CMP BL, '9'      ;;
    JG @IfLetter     ;;
    SUB BL, '0'      ;; Если BL больше '9' (т.е. символ a-f)
    jmp @EndIf       ;; То
    @IfLetter:       ;;     BL = BL - 'a' + 10
    SUB BL, 'a'      ;; Иначе
    ADD BL, 10       ;;     BL = BL - '0'
    @EndIf:          ;;
    RET              ;;
HEX_SYMBOL_TO_DEC ENDP
 
;#endregion HEX_SYMBOL_TO_DEC
 
MAIN PROC; описание процедуры
;#region Получаем дескрипторы ввода и вывода
; Аргумент функции: -10 для ввода, -11 для вывода, -12 для сообщения об ошибки
; Функция возвращает дескриптор в регистр EAX
PUSH -10
CALL GetStdHandle@4
; Перемещаем регистр вывода в новую переменную D_IN
MOV D_IN, EAX
 
PUSH -11
CALL GetStdHandle@4
; Перемещаем регистр вывода в новую переменную D_OUT
MOV D_OUT, EAX
;#endregion Получаем дескрипторы ввода и вывода
 
;#region Перекодируем строку WRITE_VALUE для DOS
; Сначала перекодируем строку STRN для DOS (т.к. она содержит русские буквы)
; Перемещаем в регистр EAX адрес строки STRN (OFFSET возвращает адрес)
MOV  EAX, OFFSET WRITE_VALUE
 
; У функции CharToOemA@8 два параметра - откуда берем строку и куда кладем
; Адрес строки
PUSH EAX; параметры функции помещаются в стек командой PUSH
PUSH EAX
CALL CharToOemA@8; вызов функции
;#endregion Перекодируем строку WRITE_VALUE для DOS
 
;#region Определяем длину строки WRITE_VALUE
; Аргумент функции: адрес строки. Возвращаемое значение: длина строки в регистре EAX
PUSH OFFSET WRITE_VALUE
CALL lstrlenA@4;
 
MOV WRITE_LENGTH, EAX
;#endregion Определяем длину строки WRITE_VALUE
 
;#region Выводим строку WRITE_VALUE
PUSH 0; 5-ый параметр всегда 0
PUSH OFFSET LENS; В переменную LENS запишется длина строки, которая была выведена
PUSH WRITE_LENGTH; Длина строки, сколько хотим вывести
PUSH OFFSET WRITE_VALUE; Адрес строки
PUSH D_OUT; Регистр вывода
CALL WriteConsoleA@20
;#endregion Выводим строку WRITE_VALUE
 
;#region Вводим строку FIRST_STRING
; FIRST_LENGTH больше на два, т.к. дополнительно введены
; 13 - возврат каретки и 10 - переход на новую строку
PUSH 0; 5-ый параметр всегда 0
PUSH OFFSET FIRST_LENGTH; Длина считанной строки строки
PUSH 50; Сколько символов хотим считать
PUSH OFFSET FIRST_STRING; Куда читаем
PUSH D_IN; Регистр ввода
CALL ReadConsoleA@20
SUB FIRST_LENGTH, 2
;#endregion Вводим строку FIRST_STRING
 
;#region Проверка на то, что длина строки больше трех
CMP FIRST_LENGTH, 3
jl string_to_small ; если строка меньше 5, то переходим прыгаем
;#endregion Проверка на то, что длина строки больше трех
 
;#region Еще раз выводим строку WRITE_VALUE
PUSH 0; 5-ый параметр всегда 0
PUSH OFFSET LENS; В переменную LENS запишется длина строки, которая была выведена
PUSH WRITE_LENGTH; Длина строки, сколько хотим вывести
PUSH OFFSET WRITE_VALUE; Адрес строки
PUSH D_OUT; Регистр вывода
CALL WriteConsoleA@20
;#endregion Еще раз выводим строку WRITE_VALUE
 
;#region Вводим строку SECOND_STRING
; 6. Вводим строку SECOND_STRING
PUSH 0; 5-ый параметр всегда 0
PUSH OFFSET SECOND_LENGTH; Длина считанной строки строки
PUSH 50; Сколько символов хотим считать
PUSH OFFSET SECOND_STRING; Куда читаем
PUSH D_IN; Регистр ввода
CALL ReadConsoleA@20
SUB SECOND_LENGTH, 2
;#endregion Вводим строку SECOND_STRING
 
;#region Проверка на то, что длина строки больше трех
CMP SECOND_LENGTH, 3
jl string_to_small ; если строка меньше 5, то переходим прыгаем
;#endregion Проверка на то, что длина строки больше трех
 
 
;#region Первая строка в dec
MOV ECX, FIRST_LENGTH
MOV ESI, OFFSET FIRST_STRING
 
XOR EAX, EAX
 
@READ_BYTES:
MOV EAX, FIRST_INT
MOV EDX, 16
MUL EDX ; Результат кладется в EDX и EAX, но т.к. число не превышает 32 бита, то EDX пуст
MOV FIRST_INT, EAX
 
DEC CL ; Уменьшаем число символов на 1
MOV BL, [ESI]            ; Читаем символ в BL
INC ESI
CALL HEX_SYMBOL_TO_DEC   ; Переводим его в число
MOV AL, BL   ;; Чтобы сложить это число с EDI
cbw          ;; перемещаем его в регистр AL
cwde         ;; и резайзим его до AX, а затем до EAX
 
ADD FIRST_INT, EAX
 
CMP ECX, 0
JG @READ_BYTES ; Если кол-во оставшихся символов больше 0, то читаем еще один байти
;#endregion Первая строка в dec
 
;#region Вторая строка в dec
MOV ECX, SECOND_LENGTH
MOV ESI, OFFSET SECOND_STRING
 
XOR EAX, EAX
 
@READ_BYTES2:
MOV EAX, SECOND_INT
MOV EDX, 16
MUL EDX ; Результат кладется в EDX и EAX, но т.к. число не превышает 32 бита, то EDX пуст
MOV SECOND_INT, EAX
 
DEC CL ; Уменьшаем число символов на 1
MOV BL, [ESI]            ; Читаем символ в BL
INC ESI
CALL HEX_SYMBOL_TO_DEC   ; Переводим его в число
MOV AL, BL   ;; Чтобы сложить это число с EDI
cbw          ;; перемещаем его в регистр AL
cwde         ;; и резайзим его до AX, а затем до EAX
 
ADD SECOND_INT, EAX
 
CMP ECX, 0
JG @READ_BYTES2 ; Если кол-во оставшихся символов больше 0, то читаем еще один байти
;#endregion Вторая строка в dec
 
 
MOV EAX, FIRST_INT
MUL SECOND_INT
 
CALL bignum
 
; TODO:
; Вывести полученное число
 
PUSH 0; параметр: код выхода
CALL ExitProcess@4
 
string_to_small:
PUSH 1;
CALL ExitProcess@4
 
MAIN ENDP
END MAIN

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎