Конкатенація строк Assembler

Курсовой проект - Компьютеры, программирование

Другие курсовые по предмету Компьютеры, программирование

PVOID lpReserved // reserved);

 

Наступна функція ReadConsole , яка вводе строку str1. Її прототип також приведен нижче.

 

BOOL ReadConsole(

HANDLE hConsoleInput, // handle to console input buffer

LPVOID lpBuffer, // data buffer

DWORD nNumberOfCharsToRead, // number of characters to read

LPDWORD lpNumberOfCharsRead, // number of characters read

LPVOID lpReserved // reserved);

 

Бачимо, що у цих двух фунціях використовуються змінні, які були пояснені раніше, тобто добре пояснення не потрібне тепер. Треба пояснити код, який використовує бібліотечні функції

 

invoke StrToFloat, ADDR str1, offset a

 

Ця функція має за мету перевод строки у змінну формата qword, яка може потім бути використаною FPU. Перейдемо тепер до основного коду функція, до коду, який обчислює функцію.

 

fld b

fld a

fcom y

fstsw ax

sahf

jz Divide

fxch

fcom y

fstsw ax

sahf jz Divide

 

fld b загружає до стека FPU значення змінної b. fcom y зрівнює цю змінну з нулем, fstsw ax sahf повертає флагі, яки булі загублені під час перевірки. jz Divide робить умовний перехід на метку Divide, якщо операнд буде рівен нулю. Це робиться для того, щоб уникнути ділення на нуль. Далі йде

ffree st(1)

ffree st(0)

fstsw ax

sahf

fld b

fld a

fcom

fstsw ax

sahf

je equal

ja greater

jb lower

jmp theend

 

Команда ffree вигружає зі стека операнди, щоб потім загрузити їх знову. Далі йде такий ж логічних русловій, але тепер перехідов більше. je equal якщо операнди рівни між собою, тоді перейти на мітку equal. Також для ja, jb, але вони перевіряються умови більше або менше відповідно. Тепер подрібніше о кожній з меток.

 

equal:

fld cons

fstp y

jmp theend

 

У цій метці до стеку загружається -2, потім ця константа передається до змінної y. По закінченню операції управління переходе до мітки theend.

 

greater:

print chr$("A IS GREATER", 13, 10)

fxch

fdiv

fld one

fadd

fstp y

jmp theend

 

У цьому блоці кода виконується ділення b на a. Яке досягається, командами fxch, fdiv. Перша потрібна для зміни міст a и b, друга діле їх друг на друга. У кінці до результату прибавляється константа 1, та усе це грузиться до y. До закінченню управління передається до мітки theend.

 

lower:

print chr$("A IS LOWER", 13, 10)

fsub st(0), st(1)

fld a

fxch

fdiv st(0), st(1)

fstp y

jmp theend

 

Мітка отримує управління, якщо a < b. У цій мітці у першу чергу пишеться у консоль, що операнд а таки менший за b. Потім від a віднімається b, загружається знову а, тому ще попереднє значення а находиться вже дальше по стеку. Та ділиться результат віднімання на а. Усе це розтащовуєть у змінній y.

 

theend:

invoke FloatToStr, y, ADDR str3

xor eax, eax

invoke szLen, offset strArithm

invoke WriteConsole, hOutPut, offset strArithm, eax, NULL, NULL

xor eax, eax

invoke szLen, ADDR str3

mov nRead1, eax

invoke WriteConsole, hOutPut, ADDR str3, nRead1, NULL, NULL

ret

 

Це остання мітка, є логічним кінцем програми. Треба тільки пояснити invoke FloatToStr, y, ADDR str3 ця функція преобразує число у строку, яка потім буде виведена на консоль.

Тепер перейдемо до наступної функції string. Допоміжна части якої, така ж як і у попередньої функції. Особої уваги вимогає invoke strCat, offset buff, offset str1. Ця функція викликає функцію конкатенації, яка буде приведена нижче.

 

strCat proc lpszSource:DWORD, lpszAdd:DWORD

push edi

invoke szLen, lpszSource

mov edi, lpszSource

mov ecx, lpszAdd

add edi, eax ; set write starting position

xor edx, edx ; zero index

xor eax, eax ; avoid stall with following AL reads and writes

mov [edi-2], byte ptr 20h

mov [edi-1], byte ptr 20h

@@:

mov al, [ecx+edx] ; write append string to end of source

mov [edi+edx], al

add edx, 1

test al, al ; exit when terminator is written

jne @B

pop edi

mov eax, lpszSource

ret

strCat endp

 

Ближче познайомимося з кодом цієї функції. У регістр edi загружається ісходна строка, до якої буде конкатинуватися інша строка, яка знаходиться у регістрі ecx. Регістр edi зміщується за розміром ісходної строки, щоб почати писати до неї з кінця. Далі йде цикл, який посимвольно додає до строки байти з іншої строки. Признаком кінця циклу є нулевий термінатор. По виходу з цікла регістр edi востанавлюється .

 

  1. Приклад виконання

 

Далі неведено декілька прикладів виконання. Наприклад якщо операнд а буде рівен 0(рис. 2. 1)

 

Рис. 2.1

 

Також примір, якщо b буде рівно 0.(Рис. 2.2)

 

Рис. 2.2

 

Тепер приклад, якщо а и б рівні(рис. 2.3).

 

Рис. 2.3

 

Тепер якщо а більше б(рис. 2.4).

 

Рис. 2.4

 

Та останній приклад, якщо а менше б(рис. 2.5)

 

Рис. 2.5

 

ВИСНОВОК

 

Згідно з завданням до курсової роботи, було розроблено три функції на мові Асемблеру, що дозволило зробити їх більш компактними та такими, що є більш ефективними з точки зору не лише кількості операцій, але й за рахунок більшого використання високошвидкісних регістрів замість памяті, де це було можливо.

 

СПИСОК ЛІТЕРАТУРИ

 

1. Абель П."Язык Ассемблер для IBM РС и программирование".

2. Нортон П."Язык Ассемблера для IBM PC".

3. Юров, Хорошенко "Assembler: учебный курс".

 

Додаток

 

.486

.model flat, stdcall

option casemap :none

include \masm32\include\windows.inc

include \masm32\macros\macros.asm

include \masm32\include\masm32.inc

include \masm32\include\gdi32.inc

include \masm32\include\user32.inc

include \masm32\include\kernel32.inc

include \masm32\include\fpu.inc

includelib \masm32\lib\masm32.lib

includelib \masm32\lib\gdi32.lib

includelib \masm32\lib\user32.lib

includelib \masm32\lib\kernel32.lib

includelib \masm32\lib\fpu.lib

strCat PROTO lpszSource:DWORD, lpszAdd:DWORD

.data

strNum1 db "Type the the first number: ", 0

strNum2 db "Type the second number: ", 0

strArithm db "The result of fucntion: ", 0

strType1 db "Type the first string: ", 0

strType2 db "Type the second string: ", 0

strResult db "The result of concationation: ", 0

strZeroDiv db "Zero divide is forbidden. Fu