1376 lines
26 KiB
PHP
1376 lines
26 KiB
PHP
; Verze: 2022.02
|
|
; Autor: Filip Orsag (orsag@fit.vutbr.cz)
|
|
;
|
|
; Podpurna knihovna funkci "rw32-20XX.inc" pro predmet ISU.
|
|
; Pro svou cinnost vyuziva standardni knihovny jazyka C.
|
|
; Lze ji pouzit v OS Windows nebo Linux.
|
|
;
|
|
; Knihovnu vkladejte na zacatek vaseho programu:
|
|
;
|
|
; %include "rw32-20XX.inc"
|
|
;
|
|
; Preklad Windows:
|
|
; nasm -f win32 -g -o helloworld.obj helloworld.asm
|
|
; golink helloworld.obj /fo helloworld.exe /console /debug coff /entry:_main msvcrt.dll kernel32.dll
|
|
;
|
|
; Preklad Linux:
|
|
; nasm -f elf32 -g -o helloworld.o helloworld.asm
|
|
; gcc -m32 -o helloworld helloworld.o
|
|
;
|
|
;
|
|
; Dostupne funkce jsou nasledujici:
|
|
;
|
|
; Cteni z klavesnice:
|
|
; (verze '_Silent' nevypisuji nic na obrazovku a v pripade chybne zadaneho cisla tuto skutecnost ignoruji)
|
|
;
|
|
; ReadChar/ReadChar_Silent
|
|
; Vstup: nic.
|
|
; Vystup: AL = hodnota znaku.
|
|
; Chovani: ceka na zadani znaku a na stisk klavesy ENTER (lze zadat i vice znaku, ale ty budou ignorovany, platny je pouze prvni znak).
|
|
|
|
; ReadString/ReadString_Silent
|
|
; Vstup: EBX = maximalni pocet znaku, ktere mohou byt nacteny.
|
|
; EDI = adresa, kam se retezec nacte (musi byt rezervovano alespon EBX+1 bytu).
|
|
; Vystup: EAX = pocet prectenych znaku
|
|
; retezec znaku ulozeny na adrese EDI.
|
|
; Chovani: nacita znaky z klavesnice, dokud neni stisknuta klavesa ENTER. Na adresu v EDI ulozi maximalne EBX znaku
|
|
; nebo mene (vsechny dalsi znaky budou ignorovany), skutecny pocet znaku vraci v registru EAX.
|
|
|
|
; ReadInt8/ReadInt8_Silent
|
|
; Vstup: nic.
|
|
; Vystup: AL = cislo z intervalu <-128, 127>.
|
|
; Chovani: cte cislo z klvesnice, umozni zadat jakykoliv znak, ale pouze znak '-','+' a cislice budou akceptovany,
|
|
; pokud neni zadana zadny znak a je stisknut ENTER, pak je vracena hodnota 0, pri prekroceni kterekoliv povolene
|
|
; meze je vraceno bud maximum nebo minimum daneho rozsahu.
|
|
|
|
; ReadInt16/ReadInt16_Silent
|
|
; Vstup: nic.
|
|
; Vystup: AX = cislo z intervalu <-32768, 32767>.
|
|
; Chovani: viz ReadInt8.
|
|
|
|
; ReadInt32/ReadInt32_Silent
|
|
; Vstup: nic.
|
|
; Vystup: EAX = cislo z intervalu <-2^31, 2^31 - 1>.
|
|
; Chovani: viz ReadInt8.
|
|
|
|
; ReadUInt8/ReadUInt8_Silent
|
|
; Vstup: nic.
|
|
; Vystup: AL = cislo z intervalu <0, 255>.
|
|
; Chovani: viz ReadInt8 s tim rozdilem, ze pri zadani znaku '-' bude cislo v doplnkovem kodu, ale interpretovano jako cislo bez znamenka.
|
|
|
|
; ReadUInt16/ReadUInt16_Silent
|
|
; Vstup: nic.
|
|
; Vystup: AX = cislo z intervalu <0, 65535>.
|
|
; Chovani: viz ReadUInt8.
|
|
|
|
; ReadUInt32/ReadUInt32_Silent
|
|
; Vstup: nic.
|
|
; Vystup: EAX = cislo z intervalu <0, 2^32 - 1>.
|
|
; Chovani: viz ReadUInt8.
|
|
|
|
; ReadFloat/ReadFloat_Silent
|
|
; Vstup: nic.
|
|
; Vystup: EAX = 32bitove realne cislo v plovouci radove carce (v jazyce C typ float).
|
|
; Chovani: viz ReadInt8, navic je dovoleno zadat znak '.' (desetinna carka) a exponent (e+N nebo e-N).
|
|
|
|
; ReadDouble/ReadDouble_Silent
|
|
; Vstup: nic.
|
|
; Vystup: ST0 = 64bitove realne cislo v plovouci radove carce (v jazyce C typ double).
|
|
; Chovani: viz ReadFloat.
|
|
|
|
; Vypis na obrazovku:
|
|
; WriteChar
|
|
; Vstup: znak v AL.
|
|
; Vystup: vypise znak na obrazovku.
|
|
|
|
; WriteNewLine
|
|
; Vstup: nic.
|
|
; Vystup: vypise konec radku ("\n").
|
|
|
|
; WriteString
|
|
; Vstup: ESI = ukazatel na retezec zakonceny hodnotou 0, ktery bude vypsan.
|
|
; Vystup: vypise retezec na obrazovku.
|
|
|
|
; WriteBin8
|
|
; Vstup: AL = cislo.
|
|
; Vystup: vypise cislo z AL na obrazovku v binarni podobe.
|
|
|
|
; WriteBin16
|
|
; Vstup: AX = cislo
|
|
; Vystup: vypise cislo z AX na obrazovku v binarni podobe.
|
|
|
|
; WriteBin32
|
|
; Vstup: EAX = cislo.
|
|
; Vystup: vypise cislo z EAX na obrazovku v binarni podobe.
|
|
|
|
; WriteHex8
|
|
; Vstup: AL = cislo.
|
|
; Vystup: vypise cislo z AL na obrazovku v hexadecimalni podobe "0xXX".
|
|
|
|
; WriteHex16
|
|
; Vstup: AX = cislo
|
|
; Vystup: vypise cislo z AX na obrazovku v hexadecimalni podobe "0xXXXX".
|
|
|
|
; WriteHex32
|
|
; Vstup: EAX = cislo.
|
|
; Vystup: vypise cislo z EAX na obrazovku v hexadecimalni podobe "0xXXXXXXXX".
|
|
|
|
; WriteInt8
|
|
; Vstup: AL = cislo.
|
|
; Vystup: vypise cislo z AL na obrazovku v dekadicke forme se znamenkem.
|
|
|
|
; WriteInt16
|
|
; Vstup: AX = cislo.
|
|
; Vystup: vypise cislo z AX na obrazovku v dekadicke forme se znamenkem.
|
|
|
|
; WriteInt32
|
|
; Vstup: EAX = cislo.
|
|
; Vystup: vypise cislo z EAX na obrazovku v dekadicke forme se znamenkem.
|
|
|
|
; WriteUInt8
|
|
; Vstup: AL = cislo.
|
|
; Vystup: vypise cislo z AL na obrazovku v dekadicke forme bez znamenka.
|
|
|
|
; WriteUInt16
|
|
; Vstup: AX = cislo.
|
|
; Vystup: vypise cislo z AX na obrazovku v dekadicke forme bez znamenka.
|
|
|
|
; WriteUInt32
|
|
; Vstup: EAX = cislo.
|
|
; Vystup: vypise cislo z EAX na obrazovku v dekadicke forme bez znamenka.
|
|
|
|
; WriteFlags
|
|
; Vstup: nic (aktualni stav priznakoveho registru).
|
|
; Vystup: vypise obsah registru priznaku EFLAGS na obrazovku.
|
|
|
|
; WriteFloat
|
|
; Vstup: EAX = cislo (realne cislo s jednoduchou presnosti - float).
|
|
; Vystup: vypise cislo z EAX na obrazovku ve forme realneho cisla.
|
|
|
|
; WriteDouble
|
|
; Vstup: ST0 = cislo (realne cislo v koprocesoru, vypisuje se cislo s dvojitou presnosti - double).
|
|
; Vystup: vypise cislo z ST0 na obrazovku ve forme realneho cisla.
|
|
;
|
|
|
|
; WriteAllGPRegisters32
|
|
; Vstup: nic (aktualni stav jednotlivych registru)
|
|
; Vystup: vypise obsah registru EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP
|
|
;
|
|
|
|
; WriteTestGPRegisters32
|
|
; Vstup: nic (aktualni stav jednotlivych registru)
|
|
; Vystup: vypise obsah registru EBX, ECX, EDX, ESI, EDI, EBP
|
|
;
|
|
|
|
; WriteArrayInt8
|
|
; Vstup: ESI = ukazatel na pole 8bitovych cisel,
|
|
; ECX = pocet prvku pole
|
|
; Vystup: vypise pole 8bitovych cisel se znamenkem
|
|
;
|
|
|
|
; WriteArrayInt16
|
|
; Vstup: ESI = ukazatel na pole 16bitovych cisel,
|
|
; ECX = pocet prvku pole
|
|
; Vystup: vypise pole 16bitovych cisel se znamenkem
|
|
;
|
|
|
|
; WriteArrayInt32
|
|
; Vstup: ESI = ukazatel na pole 32bitovych cisel,
|
|
; ECX = pocet prvku pole
|
|
; Vystup: vypise pole 32bitovych cisel se znamenkem
|
|
;
|
|
|
|
; WriteArrayUInt8
|
|
; Vstup: ESI = ukazatel na pole 8bitovych cisel,
|
|
; ECX = pocet prvku pole
|
|
; Vystup: vypise pole 8bitovych cisel bez znamenka
|
|
;
|
|
|
|
; WriteArrayUInt16
|
|
; Vstup: ESI = ukazatel na pole 16bitovych cisel,
|
|
; ECX = pocet prvku pole
|
|
; Vystup: vypise pole 16bitovych cisel bez znamenka
|
|
;
|
|
|
|
; WriteArrayUInt32
|
|
; Vstup: ESI = ukazatel na pole 32bitovych cisel,
|
|
; ECX = pocet prvku pole
|
|
; Vystup: vypise pole 32bitovych cisel bez znamenka
|
|
;
|
|
|
|
bits 32
|
|
|
|
; Funkce standardni knihovny jazyka C (C Run-Time libraray)
|
|
|
|
%ifidn __OUTPUT_FORMAT__, win32
|
|
|
|
%ifndef SASM
|
|
%macro CEXTERN 1.nolist
|
|
extern %1
|
|
%endmacro
|
|
; Nektere dalsi funkce Win32 API
|
|
CEXTERN ExitProcess
|
|
|
|
section .text
|
|
|
|
global start
|
|
start:
|
|
call _main
|
|
push dword 0
|
|
call ExitProcess
|
|
%else
|
|
%macro CEXTERN 1.nolist
|
|
%ifndef CEXTERN%1
|
|
extern _%1
|
|
%xdefine CEXTERN_%1
|
|
%xdefine %1 _%1
|
|
%endif
|
|
%endmacro
|
|
%endif
|
|
|
|
CEXTERN __iob_func
|
|
|
|
%macro PUSH_STDIN 0
|
|
cmp dword [rw_stdin],-1
|
|
jnz %%stdinOK
|
|
push eax
|
|
push 0
|
|
call __iob_func
|
|
add esp,4
|
|
mov [rw_stdin],eax
|
|
pop eax
|
|
%%stdinOK:
|
|
push dword [rw_stdin]
|
|
%endmacro
|
|
|
|
; nase vstupni funkce se bude jmenovat _main
|
|
%define CMAIN _main
|
|
|
|
%elifidn __OUTPUT_FORMAT__, elf32
|
|
|
|
%macro CEXTERN 1.nolist
|
|
extern %1
|
|
%endmacro
|
|
|
|
; nase vstupni funkce se bude jmenovat main
|
|
%define CMAIN main
|
|
|
|
extern stdin
|
|
|
|
%macro PUSH_STDIN 0
|
|
push dword [stdin]
|
|
%endmacro
|
|
%endif
|
|
|
|
global CMAIN
|
|
|
|
CEXTERN printf
|
|
CEXTERN scanf
|
|
CEXTERN sscanf
|
|
CEXTERN fgets
|
|
CEXTERN getchar
|
|
CEXTERN strlen
|
|
CEXTERN fflush
|
|
|
|
%macro STRING 2+.nolist
|
|
%1: DB %2
|
|
endof.%1: DB 0
|
|
lenof.%1 EQU endof.%1 - %1
|
|
sizeof.%1 EQU endof.%1 - %1
|
|
%endmacro
|
|
|
|
%macro INVOKE 1.nolist
|
|
call %1
|
|
%endmacro
|
|
|
|
%macro CALL_CDECL 1-*.nolist
|
|
%if %0 > 1
|
|
%rep %0-1
|
|
%rotate -1
|
|
push dword %1
|
|
%endrep
|
|
%rotate -1
|
|
%endif
|
|
call %1
|
|
add esp,(%0 - 1)*4
|
|
%endmacro
|
|
|
|
%macro CALL_PASCAL 1-*.nolist
|
|
%if %0 > 1
|
|
%rep %0-1
|
|
%rotate 1
|
|
push dword %1
|
|
%endrep
|
|
%rotate 1
|
|
%endif
|
|
call %1
|
|
%endmacro
|
|
|
|
%macro CALL_STD 1-*.nolist
|
|
%if %0 > 1
|
|
%rep %0-1
|
|
%rotate -1
|
|
push dword %1
|
|
%endrep
|
|
%rotate -1
|
|
%endif
|
|
call %1
|
|
%endmacro
|
|
|
|
%define PAR_CDECL(i,N) EBP + 4 + i*4
|
|
%define PAR_STD(i,N) EBP + 4 + i*4
|
|
%define PAR_PASCAL(i,N) EBP + 4 + N*4 - (i - 1)*4
|
|
|
|
%define RET_CDECL(N) RET
|
|
%define RET_STD(N) RET N*4
|
|
%define RET_PASCAL(N) RET N*4
|
|
|
|
%macro PRINTF 0-*.nolist
|
|
%assign incStack 0
|
|
%if %0 > 0
|
|
%rep %0
|
|
%rotate -1
|
|
%ifstr %1
|
|
section .data
|
|
%%str: db %1, 0
|
|
section .text
|
|
push %%str
|
|
%else
|
|
push dword %1
|
|
%endif
|
|
%assign incStack incStack+4
|
|
%endrep
|
|
%rotate -1
|
|
%endif
|
|
call printf
|
|
%if incStack > 0
|
|
add esp,incStack
|
|
%endif
|
|
push 0
|
|
call fflush
|
|
add esp,4
|
|
%endmacro
|
|
|
|
%imacro MOVSTR 2+
|
|
section .data
|
|
%%str: db %2, 0
|
|
section .text
|
|
mov %1,%%str
|
|
%endmacro
|
|
|
|
%imacro dbg_reg 2-*
|
|
%ifdef DEBUG
|
|
pushad
|
|
push dword %1
|
|
push msg_dump_begin_format
|
|
call printf
|
|
add esp,8
|
|
popad
|
|
%rotate 1
|
|
%assign i 0
|
|
%rep %0-1
|
|
%assign i i+1
|
|
%defstr %%dbgnamestr %1
|
|
section .data
|
|
%%dbgname %+ i: db %%dbgnamestr,0
|
|
section .text
|
|
pushad
|
|
mov [tmp],dword 0
|
|
mov [tmp], %1
|
|
push dword [tmp]
|
|
push %%dbgname %+ i
|
|
push msg_dump_format
|
|
call printf
|
|
add esp,12
|
|
popad
|
|
%undef %%dbgnamestr
|
|
%rotate 1
|
|
%endrep
|
|
pushad
|
|
push msg_dump_end_format
|
|
call printf
|
|
add esp,4
|
|
popad
|
|
%endif
|
|
%endmacro
|
|
|
|
%define KB_ENTER 0x0D
|
|
%define KB_NEWLINE 0x0A
|
|
%define KB_BACKSPACE 0x08
|
|
%define EOL KB_NEWLINE
|
|
|
|
; Konstanty
|
|
|
|
%define EOF -1
|
|
%define MAX_UBYTE 0xFF
|
|
%define MAX_UWORD 0xFFFF
|
|
%define MAX_UDWORD 0xFFFFFFFF
|
|
%define MAX_SBYTE 0x0000007F
|
|
%define MAX_SWORD 0x00007FFF
|
|
%define MAX_SDWORD 0x7FFFFFFF
|
|
%define MIN_SBYTE 0xFFFFFF80
|
|
%define MIN_SWORD 0xFFFF8000
|
|
%define MIN_SDWORD 0x80000000
|
|
%define MAX_STRING_LENGTH 1024
|
|
|
|
section .data align=4
|
|
|
|
STRING msg_EOL, `\n`
|
|
STRING msg_EnterChar, 'Zadejte znak: '
|
|
STRING msg_EnterUInt, 'Zadejte cele cislo bez znamenka z intervalu <%u,%u>: '
|
|
STRING msg_EnterSInt, 'Zadejte cele cislo se znamenkem z intervalu <%d,%d>: '
|
|
STRING msg_EnterFloat, 'Zadejte realne cislo (napr. 1.5): '
|
|
STRING msg_EnterText, 'Zadejte text (akceptovano bude maximalne %d znaku): '
|
|
STRING msg_NumberTooBig, `Cislo je prilis velke, vracim maximalni moznou hodnotu.\n`
|
|
STRING msg_NumberTooLow, `Cislo je prilis male, vracim minimalni moznou hodnotu.\n`
|
|
STRING msg_WrongNumber, 'Zadana hodnota neni rozpoznatelne cislo. Zadejte nove CISLO: '
|
|
STRING msg_NoRegChanges, 'REG CHECK OK'
|
|
STRING msg_regChanges, 'REG CHECK FAILED'
|
|
STRING s_EAX, 'EAX'
|
|
STRING s_EBX, 'EBX'
|
|
STRING s_ECX, 'ECX'
|
|
STRING s_EDX, 'EDX'
|
|
STRING s_ESI, 'ESI'
|
|
STRING s_EDI, 'EDI'
|
|
STRING s_EBP, 'EBP'
|
|
STRING s_ESP, 'ESP'
|
|
|
|
msg_dump_begin_format db "--- DEBUG BEGIN --- (at line: %d)",EOL,0
|
|
msg_dump_end_format db "--- DEBUG END ---",EOL,0
|
|
msg_dump_format db "%s = %d",EOL,0
|
|
msg_Flags db 'Flags: xxxx|OF|DF|IF|TF|SF|ZF|xx|AF|xx|PF|xx|CF|',EOL,' xxxx| '
|
|
msg_FlagValues db 'x| x| x| x| x| x| x| x| x| x| x| x|',EOL
|
|
endof_msg_Flags db 0
|
|
lenof_msg_Flags EQU endof_msg_Flags - msg_Flags
|
|
rw_stdin dd -1
|
|
number_in dq 0.0
|
|
tmp dd 0
|
|
tmpEAX dd 0
|
|
reg_dump_b dd 0,0,0,0,0,0,0,0
|
|
reg_dump dd 0
|
|
ioBuffer times MAX_STRING_LENGTH db '!'
|
|
db 0
|
|
|
|
section .text
|
|
|
|
;----------------
|
|
; Funkce ReadString/ReadString_Silent
|
|
;
|
|
%macro READ_STRING 1-2
|
|
%1:
|
|
enter 0,0
|
|
pushfd
|
|
push esi
|
|
push edi
|
|
push ebx
|
|
push ecx
|
|
push edx
|
|
|
|
%if %0 > 1
|
|
PRINTF %2, ebx
|
|
%endif
|
|
mov [edi], byte 0
|
|
test ebx,ebx
|
|
jz .return
|
|
|
|
PUSH_STDIN
|
|
push dword MAX_STRING_LENGTH
|
|
push ioBuffer
|
|
INVOKE fgets
|
|
add esp,12
|
|
|
|
mov [ioBuffer + ebx], byte 0
|
|
push ioBuffer
|
|
INVOKE strlen
|
|
add esp,4
|
|
mov ecx,eax
|
|
|
|
cmp [ioBuffer + ecx - 1], byte 10
|
|
je .is_new_line
|
|
inc ecx
|
|
.is_new_line:
|
|
mov [ioBuffer + ecx - 1], byte 0
|
|
mov esi,ioBuffer
|
|
rep movsb
|
|
|
|
.return:
|
|
pop edx
|
|
pop ecx
|
|
pop ebx
|
|
pop edi
|
|
pop esi
|
|
popfd
|
|
leave
|
|
ret
|
|
%endmacro
|
|
|
|
;----------------
|
|
; Funkce ReadString_Silent
|
|
;
|
|
READ_STRING ReadString_Silent
|
|
|
|
;----------------
|
|
; Funkce ReadString
|
|
;
|
|
READ_STRING ReadString, msg_EnterText
|
|
|
|
;----------------
|
|
; Funkce ReadChar_Silent
|
|
;
|
|
ReadChar_Silent:
|
|
enter 0,0
|
|
pushfd
|
|
push esi
|
|
push ecx
|
|
push edx
|
|
jmp ReadChar.skipMsg
|
|
;----------------
|
|
; Funkce ReadChar
|
|
;
|
|
ReadChar:
|
|
enter 0,0
|
|
pushfd
|
|
push esi
|
|
push ecx
|
|
push edx
|
|
|
|
mov esi,msg_EnterChar
|
|
call WriteString
|
|
|
|
.skipMsg:
|
|
|
|
PUSH_STDIN
|
|
push dword MAX_STRING_LENGTH
|
|
push ioBuffer
|
|
INVOKE fgets
|
|
add esp,12
|
|
|
|
movzx eax,byte [ioBuffer]
|
|
|
|
.return:
|
|
pop edx
|
|
pop ecx
|
|
pop esi
|
|
popfd
|
|
leave
|
|
ret
|
|
|
|
|
|
;----------------
|
|
; Funkce ReadNumber/ReadNumber_Silent
|
|
; Cte cislo ze standardniho vstupu dle formatovaciho retezce odpovidajiciho formatu scanf.
|
|
; Ukazatel na formatovaci retezec je ulozen v registru EBX.
|
|
;
|
|
%macro READ_NUMBER 1-2
|
|
%1:
|
|
enter 0,0
|
|
push ebx
|
|
push ecx
|
|
push edx
|
|
|
|
.again:
|
|
mov [number_in], dword 0
|
|
mov [number_in + 4], dword 0
|
|
|
|
PUSH_STDIN
|
|
push MAX_STRING_LENGTH
|
|
push ioBuffer
|
|
INVOKE fgets
|
|
add esp,12
|
|
|
|
push number_in
|
|
push ebx
|
|
push ioBuffer
|
|
INVOKE sscanf
|
|
add esp,12
|
|
cmp eax,0
|
|
jne .ok
|
|
|
|
%if %0 > 1
|
|
PRINTF "%s", %2
|
|
jmp .again
|
|
%endif
|
|
.ok:
|
|
mov eax,[number_in]
|
|
|
|
pop edx
|
|
pop ecx
|
|
pop ebx
|
|
leave
|
|
ret
|
|
%endmacro
|
|
|
|
;----------------
|
|
; Funkce ReadNumber_Silent
|
|
;
|
|
READ_NUMBER ReadNumber_Silent
|
|
|
|
;----------------
|
|
; Funkce ReadNumber
|
|
;
|
|
READ_NUMBER ReadNumber, msg_WrongNumber
|
|
|
|
%macro CREATE_READNUMBER_PROLOGUE 5-6
|
|
%1:
|
|
enter 0,0
|
|
push esi
|
|
push edi
|
|
push ebx
|
|
mov edi,%2
|
|
mov ebx,%3
|
|
%if %0 > 5
|
|
push ecx
|
|
push edx
|
|
PRINTF %6, edi, ebx
|
|
pop edx
|
|
pop ecx
|
|
push ebx
|
|
MOVSTR ebx,%5
|
|
call ReadNumber
|
|
pop ebx
|
|
jmp %4
|
|
%else
|
|
push ebx
|
|
MOVSTR ebx,%5
|
|
call ReadNumber_Silent
|
|
pop ebx
|
|
jmp %4
|
|
%endif
|
|
%endmacro
|
|
|
|
;----------------
|
|
; Funkce ReadIntX (8,16,32) {ReadInt8,ReadInt16,ReadInt32}
|
|
; Precte 8-, 16-, 32-bitovou celociselnou hodnotu se znamenkem z klavesnice
|
|
; Chovani funkci je dano chovanim funkce SSCANF. Veskere namitky se netykaji autora.
|
|
;
|
|
CREATE_READNUMBER_PROLOGUE ReadInt8,MIN_SBYTE,MAX_SBYTE,ReadInt,"%d",msg_EnterSInt
|
|
CREATE_READNUMBER_PROLOGUE ReadInt16,MIN_SWORD,MAX_SWORD,ReadInt,"%d",msg_EnterSInt
|
|
CREATE_READNUMBER_PROLOGUE ReadInt32,MIN_SDWORD,MAX_SDWORD,ReadInt,"%d",msg_EnterSInt
|
|
CREATE_READNUMBER_PROLOGUE ReadInt8_Silent,MIN_SBYTE,MAX_SBYTE,ReadInt,"%d"
|
|
CREATE_READNUMBER_PROLOGUE ReadInt16_Silent,MIN_SWORD,MAX_SWORD,ReadInt,"%d"
|
|
CREATE_READNUMBER_PROLOGUE ReadInt32_Silent,MIN_SDWORD,MAX_SDWORD,ReadInt,"%d"
|
|
|
|
ReadInt:
|
|
cmp eax,ebx
|
|
jng .test_min
|
|
|
|
; mov esi,msg_NumberTooBig
|
|
; call WriteString
|
|
mov eax,ebx
|
|
jmp .return
|
|
|
|
.test_min:
|
|
cmp eax,edi
|
|
jnl .return
|
|
|
|
; mov esi,msg_NumberTooLow
|
|
; call WriteString
|
|
mov eax,edi
|
|
|
|
.return:
|
|
pop ebx
|
|
pop edi
|
|
pop esi
|
|
leave
|
|
ret
|
|
|
|
;----------------
|
|
; Funkce ReadUIntX (8,16,32) {ReadUInt8,ReadUInt16,ReadUInt32}
|
|
; Precte 8-, 16-, 32-bitovou celociselnou hodnotu bez znamenka z klavesnice
|
|
; Chovani funkci je dano chovanim funkce SSCANF. Veskere namitky se netykaji autora.
|
|
;
|
|
CREATE_READNUMBER_PROLOGUE ReadUInt8,0,MAX_UBYTE,ReadUInt,"%u",msg_EnterUInt
|
|
CREATE_READNUMBER_PROLOGUE ReadUInt16,0,MAX_UWORD,ReadUInt,"%u",msg_EnterUInt
|
|
CREATE_READNUMBER_PROLOGUE ReadUInt32,0,MAX_UDWORD,ReadUInt,"%u",msg_EnterUInt
|
|
CREATE_READNUMBER_PROLOGUE ReadUInt8_Silent,0,MAX_UBYTE,ReadUInt,"%u"
|
|
CREATE_READNUMBER_PROLOGUE ReadUInt16_Silent,0,MAX_UWORD,ReadUInt,"%u"
|
|
CREATE_READNUMBER_PROLOGUE ReadUInt32_Silent,0,MAX_UDWORD,ReadUInt,"%u"
|
|
|
|
ReadUInt:
|
|
cmp eax,ebx
|
|
jna .return
|
|
|
|
; mov esi,msg_NumberTooBig
|
|
; call WriteString
|
|
mov eax,ebx
|
|
|
|
.return:
|
|
pop ebx
|
|
pop edi
|
|
pop esi
|
|
leave
|
|
ret
|
|
|
|
;----------------
|
|
; Funkce ReadFloat
|
|
; Precte 32bitove realne cislo z klavesnice
|
|
; Chovani funkci je dano chovanim funkce SSCANF. Veskere namitky se netykaji autora.
|
|
;
|
|
ReadFloat:
|
|
enter 0,0
|
|
pushfd
|
|
push esi
|
|
push ebx
|
|
|
|
mov esi,msg_EnterFloat
|
|
call WriteString
|
|
MOVSTR ebx,"%lf"
|
|
call ReadNumber
|
|
fld qword [number_in]
|
|
sub esp,4
|
|
fstp dword [esp]
|
|
pop eax
|
|
|
|
.return:
|
|
|
|
pop ebx
|
|
pop esi
|
|
popfd
|
|
leave
|
|
ret
|
|
|
|
ReadFloat_Silent:
|
|
enter 0,0
|
|
pushfd
|
|
push ebx
|
|
|
|
MOVSTR ebx,"%lf"
|
|
call ReadNumber_Silent
|
|
fld qword [number_in]
|
|
sub esp,4
|
|
fstp dword [esp]
|
|
pop eax
|
|
|
|
.return:
|
|
|
|
pop ebx
|
|
popfd
|
|
leave
|
|
ret
|
|
|
|
;----------------
|
|
; Funkce ReadDouble
|
|
; Precte 64bitove realne cislo z klavesnice
|
|
; Chovani funkci je dano chovanim funkce SSCANF. Veskere namitky se netykaji autora.
|
|
;
|
|
ReadDouble:
|
|
enter 0,0
|
|
pushfd
|
|
push esi
|
|
push ebx
|
|
push eax
|
|
|
|
mov esi,msg_EnterFloat
|
|
call WriteString
|
|
MOVSTR ebx,"%lf"
|
|
call ReadNumber
|
|
fld qword [number_in]
|
|
|
|
.return:
|
|
|
|
pop eax
|
|
pop ebx
|
|
pop esi
|
|
popfd
|
|
leave
|
|
ret
|
|
|
|
ReadDouble_Silent:
|
|
enter 0,0
|
|
pushfd
|
|
push ebx
|
|
push eax
|
|
|
|
MOVSTR ebx,"%lf"
|
|
call ReadNumber_Silent
|
|
fld qword [number_in]
|
|
|
|
.return:
|
|
|
|
pop eax
|
|
pop ebx
|
|
popfd
|
|
leave
|
|
ret
|
|
;----------------
|
|
; WriteChar
|
|
; Vypise znak ulozeny v registru AL
|
|
;
|
|
WriteChar:
|
|
enter 0,0
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
|
|
PRINTF "%c",eax
|
|
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
leave
|
|
ret
|
|
|
|
;----------------
|
|
; WriteNewLine
|
|
; Vypise "End Of Line", tedy ASCII hodnoty CR, LF ve Windows (13, 10) a LF v Linuxu (10)
|
|
;
|
|
WriteNewLine:
|
|
enter 0,0
|
|
pushfd
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
|
|
PRINTF "%s",msg_EOL
|
|
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
popfd
|
|
leave
|
|
ret
|
|
|
|
;----------------
|
|
; Funkce WriteBinX (8, 16, 32) {WriteBin8, WriteBin16, WriteBin32}
|
|
; Vypise 8,16,32 bitu z registru AL, AX, EAX
|
|
;
|
|
WriteBin8:
|
|
enter 0,0
|
|
pushfd
|
|
pushad
|
|
|
|
mov ecx,8
|
|
rcl eax,24
|
|
jmp WriteBin
|
|
|
|
WriteBin16:
|
|
enter 0,0
|
|
pushfd
|
|
pushad
|
|
|
|
mov ecx,16
|
|
rcl eax,16
|
|
jmp WriteBin
|
|
|
|
WriteBin32:
|
|
enter 0,0
|
|
pushfd
|
|
pushad
|
|
|
|
mov ecx,32
|
|
|
|
WriteBin:
|
|
cld
|
|
mov edi,ioBuffer
|
|
mov ebx,eax
|
|
|
|
.next_bit:
|
|
rcl ebx,1
|
|
setc al
|
|
add al,'0'
|
|
stosb
|
|
loop .next_bit
|
|
|
|
mov [edi], byte 0
|
|
mov esi,ioBuffer
|
|
call WriteString
|
|
|
|
popad
|
|
popfd
|
|
leave
|
|
ret
|
|
|
|
;----------------
|
|
; WriteString
|
|
; Vypise retezce ukonceneho 0 (ASCIIZ), jehoz adresa je ulozena v registru ESI
|
|
;
|
|
WriteString:
|
|
enter 0,0
|
|
;pushfd
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
|
|
PRINTF "%s", esi
|
|
|
|
sub eax,eax
|
|
stc
|
|
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
|
|
;popfd
|
|
leave
|
|
ret
|
|
|
|
;----------------
|
|
; WriteFlags
|
|
; Vypise stav registru priznaku
|
|
;
|
|
WriteFlags:
|
|
enter 0,0
|
|
pushfd
|
|
pushad
|
|
|
|
pushfd
|
|
pop ebx
|
|
shl ebx,20
|
|
|
|
mov ecx,12
|
|
mov edi,msg_FlagValues
|
|
|
|
.cycle:
|
|
rcl ebx,1
|
|
setc al
|
|
add al,'0'
|
|
mov [edi],al
|
|
add edi,3
|
|
loop .cycle
|
|
|
|
mov esi,msg_Flags
|
|
call WriteString
|
|
|
|
popad
|
|
popfd
|
|
leave
|
|
ret
|
|
|
|
;----------------
|
|
; Funkce WriteIntX (8,16,32) {WriteInt8,WriteInt16,WriteInt32}
|
|
; Vypise 8-, 16-, 32-bitovou celociselnou hodnotu se znamenkem z registru AL, AX, EAX
|
|
;
|
|
;----------------
|
|
; Funkce WriteUIntX (8,16,32) {WriteUInt8,WriteUInt16,WriteUInt32}
|
|
; Vypise 8-, 16-, 32-bitovou celociselnou hodnotu bez znamenka z registru AL, AX, EAX
|
|
;
|
|
; Chovani funkci je dano chovanim funkce PRINTF a prislusnym formatovacim retezcem.
|
|
;
|
|
|
|
WriteInt8:
|
|
enter 0,0
|
|
pushfd
|
|
push eax
|
|
movsx eax,al
|
|
jmp WriteInt
|
|
|
|
WriteUInt8:
|
|
enter 0,0
|
|
pushfd
|
|
push eax
|
|
movzx eax,al
|
|
jmp WriteUInt
|
|
|
|
WriteInt16:
|
|
enter 0,0
|
|
pushfd
|
|
push eax
|
|
movsx eax,ax
|
|
jmp WriteInt
|
|
|
|
WriteUInt16:
|
|
enter 0,0
|
|
pushfd
|
|
push eax
|
|
movzx eax,ax
|
|
jmp WriteUInt
|
|
|
|
WriteInt32:
|
|
enter 0,0
|
|
pushfd
|
|
push eax
|
|
|
|
WriteInt:
|
|
push ecx
|
|
push edx
|
|
|
|
PRINTF "%d", eax
|
|
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
popfd
|
|
leave
|
|
ret
|
|
|
|
WriteUInt32:
|
|
enter 0,0
|
|
pushfd
|
|
push eax
|
|
|
|
WriteUInt:
|
|
push ecx
|
|
push edx
|
|
|
|
PRINTF "%u", eax
|
|
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
popfd
|
|
leave
|
|
ret
|
|
|
|
;----------------
|
|
; Funkce WriteHexX (8,16,32) {WriteHex8,WriteHex16,WriteHex32}
|
|
; Vypise hexadecimalne 8-, 16-, 32-bitovou celociselnou hodnotu bez znamenka z registru AL, AX, EAX
|
|
;
|
|
; Chovani funkci je dano chovanim funkce PRINTF a prislusnym formatovacim retezcem.
|
|
;
|
|
|
|
WriteHex8:
|
|
enter 0,0
|
|
pushfd
|
|
push eax
|
|
push esi
|
|
movzx eax,al
|
|
MOVSTR esi,"0x%02X"
|
|
jmp WriteHex
|
|
|
|
WriteHex16:
|
|
enter 0,0
|
|
pushfd
|
|
push eax
|
|
push esi
|
|
movzx eax,ax
|
|
MOVSTR esi,"0x%04X"
|
|
jmp WriteHex
|
|
|
|
WriteHex32:
|
|
enter 0,0
|
|
pushfd
|
|
push eax
|
|
push esi
|
|
MOVSTR esi,"0x%08X"
|
|
|
|
WriteHex:
|
|
push ecx
|
|
push edx
|
|
|
|
PRINTF esi, eax
|
|
|
|
pop edx
|
|
pop ecx
|
|
pop esi
|
|
pop eax
|
|
popfd
|
|
leave
|
|
ret
|
|
|
|
;----------------
|
|
; Funkce WriteFloat
|
|
; Vypise 32-bitove realne cislo z registru EAX
|
|
;
|
|
WriteFloat:
|
|
enter 0,0
|
|
pushfd
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
|
|
push eax
|
|
fld dword [esp]
|
|
sub esp, 4
|
|
fstp qword [esp]
|
|
PRINTF "%f" ; printf vyzaduje vzdy double!
|
|
add esp,8
|
|
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
popfd
|
|
leave
|
|
ret
|
|
|
|
;----------------
|
|
; Funkce WriteFloat
|
|
; Vypise 32-bitove realne cislo z registru EAX
|
|
;
|
|
WriteFloatP1:
|
|
enter 0,0
|
|
pushfd
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
|
|
push eax
|
|
fld dword [esp]
|
|
sub esp, 4
|
|
fstp qword [esp]
|
|
PRINTF "%.1f" ; printf vyzaduje vzdy double!
|
|
add esp,8
|
|
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
popfd
|
|
leave
|
|
ret
|
|
|
|
;----------------
|
|
; Funkce WriteDouble
|
|
; Vypise 64-bitove realne cislo z registru koprocesoru ST0
|
|
;
|
|
WriteDouble:
|
|
enter 0,0
|
|
pushfd
|
|
push eax
|
|
push ecx
|
|
push edx
|
|
|
|
sub esp,8
|
|
fst qword [esp]
|
|
PRINTF "%lf"
|
|
add esp,8
|
|
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
popfd
|
|
leave
|
|
ret
|
|
|
|
;----------------
|
|
; Funkce WriteAllGPRegisters32
|
|
; Vypise pole cisel, ukazatel na pole je v ESI, pocet cisel je v ECX
|
|
;
|
|
WriteAllGPRegisters32:
|
|
pushfd
|
|
pushad
|
|
PRINTF `EAX=0x%08X,EBX=0x%08X,ECX=0x%08X,EDX=0x%08X,ESI=0x%08X,EDI=0x%08X,EBP=0x%08X,ESP=0x%08X\n`, eax, ebx, ecx, edx, esi, edi, ebp, esp
|
|
popad
|
|
popfd
|
|
ret
|
|
|
|
;----------------
|
|
; Funkce WriteTestGPRegisters32
|
|
; Vypise pole cisel, ukazatel na pole je v ESI, pocet cisel je v ECX
|
|
;
|
|
WriteTestGPRegisters32:
|
|
pushfd
|
|
pushad
|
|
PRINTF `EBX=0x%08X,ECX=0x%08X,EDX=0x%08X,ESI=0x%08X,EDI=0x%08X,EBP=0x%08X\n`, ebx, ecx, edx, esi, edi, ebp
|
|
popad
|
|
popfd
|
|
ret
|
|
|
|
RegDump:
|
|
mov [tmp],esp
|
|
mov esp,reg_dump+4
|
|
pushad
|
|
mov esp,[tmp]
|
|
mov [reg_dump - 16],esp
|
|
ret
|
|
|
|
;----------------
|
|
; Funkce WriteDiffTestGPRegisters32
|
|
; Vypise pole cisel, ukazatel na pole je v ESI, pocet cisel je v ECX
|
|
;
|
|
WriteDiffTestGPRegisters32:
|
|
;EAX ~ ESP + 28 (-0)
|
|
;ECX ~ ESP + 24 (-4)
|
|
;EDX ~ ESP + 20 (-8)
|
|
;EBX ~ ESP + 16 (-12)
|
|
;old ESP ~ ESP + 12 (-16)
|
|
;EBP ~ ESP + 8 (-20)
|
|
;ESI ~ ESP + 4 (-24)
|
|
;EDI ~ ESP + 0 (-28)
|
|
|
|
mov [tmp],esp
|
|
pushfd
|
|
pushad
|
|
mov ebp,esp
|
|
; cmp eax,[reg_dump - 0]
|
|
; jz .ebx
|
|
; push s_EAX
|
|
;.ebx:
|
|
cmp ebx,[reg_dump - 12]
|
|
jz .ecx
|
|
push s_EBX
|
|
.ecx:
|
|
cmp ecx,[reg_dump - 4]
|
|
jz .edx
|
|
push s_ECX
|
|
.edx:
|
|
cmp edx,[reg_dump - 8]
|
|
jz .esi
|
|
push s_EDX
|
|
.esi:
|
|
cmp esi,[reg_dump - 24]
|
|
jz .edi
|
|
push s_ESI
|
|
.edi:
|
|
cmp edi,[reg_dump - 28]
|
|
jz .ebp
|
|
push s_EDI
|
|
.ebp:
|
|
mov eax,[ebp + 8]
|
|
cmp eax,[reg_dump - 20]
|
|
jz .esp
|
|
push s_EBP
|
|
.esp:
|
|
mov eax,[tmp]
|
|
cmp eax,[reg_dump - 16]
|
|
jz .write
|
|
push s_ESP
|
|
.write:
|
|
mov ecx,ebp
|
|
sub ecx,esp
|
|
shr ecx,2
|
|
cmp ecx,0
|
|
jz .no_changes
|
|
mov esi,msg_regChanges
|
|
call WriteString
|
|
.write_next:
|
|
pop esi
|
|
; call WriteString
|
|
cmp ecx,1
|
|
jz .skip_comma
|
|
mov al,','
|
|
; call WriteChar
|
|
.skip_comma:
|
|
loop .write_next
|
|
jmp .exit
|
|
.no_changes:
|
|
mov esi,msg_NoRegChanges
|
|
call WriteString
|
|
.exit:
|
|
;call WriteNewLine
|
|
popad
|
|
popfd
|
|
ret
|
|
|
|
;----------------
|
|
; Funkce WriteDiffTestGPRegisters32
|
|
; Vypise pole cisel, ukazatel na pole je v ESI, pocet cisel je v ECX
|
|
;
|
|
HaveGPRegisters32Changed:
|
|
;EAX ~ ESP + 28 (-0)
|
|
;ECX ~ ESP + 24 (-4)
|
|
;EDX ~ ESP + 20 (-8)
|
|
;EBX ~ ESP + 16 (-12)
|
|
;old ESP ~ ESP + 12 (-16)
|
|
;EBP ~ ESP + 8 (-20)
|
|
;ESI ~ ESP + 4 (-24)
|
|
;EDI ~ ESP + 0 (-28)
|
|
mov [tmp],esp
|
|
pushfd
|
|
pushad
|
|
mov ebp,esp
|
|
cmp ebx,[reg_dump - 12]
|
|
jnz .changed
|
|
cmp ecx,[reg_dump - 4]
|
|
jnz .changed
|
|
cmp edx,[reg_dump - 8]
|
|
jnz .changed
|
|
cmp esi,[reg_dump - 24]
|
|
jnz .changed
|
|
cmp edi,[reg_dump - 28]
|
|
jnz .changed
|
|
mov eax,[ebp + 8]
|
|
cmp eax,[reg_dump - 20]
|
|
jnz .changed
|
|
mov eax,[tmp]
|
|
cmp eax,[reg_dump - 16]
|
|
jnz .changed
|
|
mov [tmpEAX],dword 1
|
|
jmp .exit
|
|
.changed:
|
|
mov [tmpEAX],dword 0
|
|
.exit:
|
|
popad
|
|
popfd
|
|
mov eax,[tmpEAX]
|
|
ret
|
|
|
|
%macro CREATE_WRITE_ARRAY 2.nolist
|
|
; datovy typ (b,w,d), funkce pro vypis z RW32
|
|
WriteArray%2:
|
|
enter 0,0
|
|
pushfd
|
|
push esi
|
|
push ecx
|
|
push eax
|
|
|
|
test esi,esi
|
|
jnz %%ptr_ok
|
|
PRINTF 'NULL'
|
|
jmp %%exit
|
|
%%ptr_ok:
|
|
mov al,'['
|
|
call WriteChar
|
|
cmp ecx,0
|
|
jle %%end
|
|
%%writeElement:
|
|
lods%1
|
|
call Write%2
|
|
cmp ecx,1
|
|
jbe %%skipComma
|
|
mov al,','
|
|
call WriteChar
|
|
mov al,' '
|
|
call WriteChar
|
|
%%skipComma:
|
|
loop %%writeElement
|
|
%%end:
|
|
mov al,']'
|
|
call WriteChar
|
|
;call WriteNewLine
|
|
%%exit:
|
|
pop eax
|
|
pop ecx
|
|
pop esi
|
|
popfd
|
|
leave
|
|
ret
|
|
%endmacro
|
|
|
|
;----------------
|
|
; Funkce WriteArrayInt8
|
|
; Vypise pole cisel, ukazatel na pole je v ESI, pocet cisel je v ECX
|
|
;
|
|
CREATE_WRITE_ARRAY b, Int8
|
|
|
|
;----------------
|
|
; Funkce WriteArrayInt16
|
|
; Vypise pole cisel, ukazatel na pole je v ESI, pocet cisel je v ECX
|
|
;
|
|
CREATE_WRITE_ARRAY w, Int16
|
|
|
|
;----------------
|
|
; Funkce WriteArrayInt32
|
|
; Vypise pole cisel, ukazatel na pole je v ESI, pocet cisel je v ECX
|
|
;
|
|
CREATE_WRITE_ARRAY d, Int32
|
|
|
|
;----------------
|
|
; Funkce WriteArrayUInt8
|
|
; Vypise pole cisel, ukazatel na pole je v ESI, pocet cisel je v ECX
|
|
;
|
|
CREATE_WRITE_ARRAY b, UInt8
|
|
|
|
;----------------
|
|
; Funkce WriteArrayUInt16
|
|
; Vypise pole cisel, ukazatel na pole je v ESI, pocet cisel je v ECX
|
|
;
|
|
CREATE_WRITE_ARRAY w, UInt16
|
|
|
|
;----------------
|
|
; Funkce WriteArrayUInt32
|
|
; Vypise pole cisel, ukazatel na pole je v ESI, pocet cisel je v ECX
|
|
;
|
|
CREATE_WRITE_ARRAY d, UInt32
|
|
|
|
;----------------
|
|
; Funkce WriteArrayFloat
|
|
; Vypise pole cisel, ukazatel na pole je v ESI, pocet cisel je v ECX
|
|
;
|
|
CREATE_WRITE_ARRAY d, Float
|
|
|
|
;----------------
|
|
; Funkce WriteArrayFloatP1
|
|
; Vypise pole cisel, ukazatel na pole je v ESI, pocet cisel je v ECX
|
|
;
|
|
CREATE_WRITE_ARRAY d, FloatP1
|
|
|