; 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