Skip to content

Instantly share code, notes, and snippets.

@lucansky
Created December 26, 2014 13:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lucansky/03e09348dc5a418f4bd4 to your computer and use it in GitHub Desktop.
Save lucansky/03e09348dc5a418f4bd4 to your computer and use it in GitHub Desktop.
RW32 Clib assembly (IAS)
;
; Podpurna knihovna funkci rw32_clib.inc pro predmet IAS.
; Pro svou cinnost vyuziva standardni knihovny jazyka C.
; Lze ji pouzit v OS Windows nebo Linux.
; Pro preklad je potreba program NASM.
; Pro sestaveni ve Windows je potreba napriklad ALINK, v Linuxu GCC
;
; Verze: 2012.11.09
; Autor: Filip Orsag (orsag@fit.vutbr.cz)
;
; Priklad prekladu ve Windows a Linuxu:
;
; Windows
; nasm -fobj test_clib.asm
; alink -oPE -subsys console test_clib.obj
;
; Linux:
; nasm -felf32 test_clib.asm
; gcc -o test_clib test_clib.o
;
;
; Knihovnu vkladejte na zacatek vaseho programu. Dostupne funkce jsou nasledujici:
;
; Cteni z klavesnice:
; ReadChar
; 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
; 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
; 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
; Vstup: nic.
; Vystup: AX = cislo z intervalu <-32768, 32767>.
; Chovani: viz ReadInt8.
; ReadInt32
; Vstup: nic.
; Vystup: EAX = cislo z intervalu <-2^31, 2^31 - 1>.
; Chovani: viz ReadInt8.
; ReadUInt8
; 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
; Vstup: nic.
; Vystup: AX = cislo z intervalu <0, 65535>.
; Chovani: viz ReadUInt8.
; ReadUInt32
; Vstup: nic.
; Vystup: EAX = cislo z intervalu <0, 2^32 - 1>.
; Chovani: viz ReadUInt8.
; ReadFloat
; 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
; 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 (MS-DOS varianta end-of-line = hodnoty 13, 10, v Linuxu pouze 10).
; 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.
; 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 priznakoveho registru priznaku 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.
;
bits 32
cpu X64
; Funkce standardni knihovny jazyka C (C Run-Time libraray)
extern printf
extern scanf
extern sscanf
extern gets
extern getchar
extern strlen
extern strtoul
extern strtol
extern strtod
extern _errno
%ifidn __OUTPUT_FORMAT__, obj
; Import funkci ze standardni knihovny jazyka C - msvcrt.dll
import printf msvcrt
import scanf msvcrt
import sscanf msvcrt
import gets msvcrt
import getchar msvcrt
import strlen msvcrt
import strtoul msvcrt
import strtol msvcrt
import strtod msvcrt
import _errno msvcrt
; Nektere dalsi funkce Win32 API
extern ExitProcess
import ExitProcess kernel32.dll
extern GetModuleHandleA
import GetModuleHandleA kernel32.dll
; Makra Win32
%define KB_ENTER 0x0D
%define KB_NEWLINE 0x0A
%define KB_BACKSPACE 0x08
%define EOL KB_ENTER,KB_NEWLINE
%macro invoke 1
call [%1]
%endmacro
%macro prologue 0
..start:
invoke _errno
mov [errno],eax
push dword 0
invoke GetModuleHandleA
mov [hInstance],eax
%endmacro
%macro epilogue 0
xor eax,eax
push dword 0
invoke ExitProcess
ret
%endmacro
%elifidn __OUTPUT_FORMAT__, elf32
global main
; Makra Linux32
%define KB_ENTER 0x0D
%define KB_NEWLINE 0x0A
%define KB_BACKSPACE 0x08
%define EOL KB_NEWLINE
%macro invoke 1
call %1
%endmacro
%macro prologue 0
main:
push esi
push edi
%endmacro
%macro epilogue 0
xor eax,eax
pop edi
pop esi
ret
%endmacro
%else
%fatal "Tato knihovna vyzaduje format prekladu bud OBJ (-f obj) nebo ELF32 (-f elf32)."
%endif
%macro string 2+
%1: DB %2
endof.%1: DB 0
lenof.%1 EQU endof.%1 - %1
sizeof.%1 EQU endof.%1 - %1
%endmacro
; 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
%ifidn __OUTPUT_FORMAT__, obj
[section .rw32_data use32 class=DATA align=4]
%elifidn __OUTPUT_FORMAT__, elf32
[section .data align=4]
%endif
string msg_EOL, EOL
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_EnterString, 'Zadejte text (akceptovano bude maximalne %d znaku): '
string msg_NumberTooBig, 'Cislo je prilis velke, vracim maximalni moznou hodnotu.', EOL
string msg_NumberTooLow, 'Cislo je prilis male, vracim minimalni moznou hodnotu.', EOL
string msg_WrongNumber, 'Zadana hodnota neni rozpoznatelne cislo. Zadejte nove CISLO: '
errno dd 0
format_char db "%c",0
format_string db "%s",0
format_int db "%d",0
format_uint db "%u",0
format_float db "%f",0
format_double db "%lf",0
format_char_in db "%c",0
format_int_in db "%d",0
format_uint_in db "%u",0
format_real_in db "%lf",0
msg_Flags db 'Flags: xxxx|OF|DF|IF|TF|SF|ZF|xx|AF|xx|PF|xx|CF|',13,10,' 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
hInstance dd 0
number_in dq 0.0
ioBuffer times MAX_STRING_LENGTH db '!'
db 0
%ifidn __OUTPUT_FORMAT__, obj
[section .rw32_code use32 class=CODE]
%elifidn __OUTPUT_FORMAT__, elf32
[section .text]
%endif
;----------------
; Funkce ReadChar
;
ReadChar:
push esi
mov esi,msg_EnterChar
call WriteString
invoke getchar
push eax
.next:
cmp eax,KB_NEWLINE
jz .return
cmp eax,EOF
jz .return
invoke getchar
jmp .next
.return:
pop eax
pop esi
ret
;----------------
; Funkce ReadString
;
ReadString:
pushfd
push esi
push edi
push ebx
push ecx
push edx
push ebx
push msg_EnterString
invoke printf
add esp,8
mov [edi], byte 0
cmp ebx,0
je .return
push ioBuffer
invoke gets
mov [ioBuffer + ebx], byte 0
invoke strlen
add esp,4
mov ecx,eax
inc ecx
push edi
mov esi,ioBuffer
rep movsb
pop edi
.return:
pop edx
pop ecx
pop ebx
pop edi
pop esi
popfd
ret
;----------------
; Funkce ReadNumber
; Cte cislo ze standardniho vstupu dle formatovaciho retezce odpovidajiciho formatu scanf.
; Ukazatel na formatovaci retezec je ulozen v registru EBX.
;
ReadNumber:
push ebx
push ecx
push edx
.again:
mov [number_in], dword 0
mov [number_in + 4], dword 0
push ioBuffer
invoke gets
add esp,4
push number_in
push ebx
push ioBuffer
invoke sscanf
add esp,12
cmp eax,0
jne .ok
push msg_WrongNumber
push format_string
invoke printf
add esp,8
jmp .again
.ok:
mov eax,[number_in]
pop edx
pop ecx
pop ebx
ret
;----------------
; 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.
;
ReadInt8:
push esi
push edi
push ebx
mov ebx,MAX_SBYTE
mov edi,MIN_SBYTE
jmp ReadInt
ReadInt16:
push esi
push edi
push ebx
mov ebx,MAX_SWORD
mov edi,MIN_SWORD
jmp ReadInt
ReadInt32:
push esi
push edi
push ebx
mov ebx,MAX_SDWORD
mov edi,MIN_SDWORD
ReadInt:
push ecx
push edx
push ebx
push edi
push msg_EnterSInt
invoke printf
add esp,12
pop edx
pop ecx
push ebx
mov ebx,format_int_in
call ReadNumber
pop ebx
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
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.
;
ReadUInt8:
push esi
push edi
push ebx
mov ebx,MAX_UBYTE
mov edi,0
jmp ReadUInt
ReadUInt16:
push esi
push edi
push ebx
mov ebx,MAX_UWORD
mov edi,0
jmp ReadUInt
ReadUInt32:
push esi
push edi
push ebx
mov ebx,MAX_UDWORD
mov edi,0
ReadUInt:
push ecx
push edx
push ebx
push edi
push msg_EnterUInt
invoke printf
add esp,12
pop edx
pop ecx
push ebx
mov ebx,format_uint_in
call ReadNumber
pop ebx
cmp eax,ebx
jna .return
mov esi,msg_NumberTooBig
call WriteString
mov eax,ebx
.return:
pop ebx
pop edi
pop esi
ret
;----------------
; Funkce ReadFloat
; Precte 32bitove realne cislo z klavesnice
; Chovani funkci je dano chovanim funkce SSCANF. Veskere namitky se netykaji autora.
;
ReadFloat:
pushfd
push esi
push ebx
mov esi,msg_EnterFloat
call WriteString
mov ebx,format_real_in
call ReadNumber
fld qword [number_in]
sub esp,4
fstp dword [esp]
pop eax
.return:
pop ebx
pop esi
popfd
ret
;----------------
; Funkce ReadDouble
; Precte 64bitove realne cislo z klavesnice
; Chovani funkci je dano chovanim funkce SSCANF. Veskere namitky se netykaji autora.
;
ReadDouble:
pushfd
push esi
push ebx
push eax
mov esi,msg_EnterFloat
call WriteString
mov ebx,format_real_in
call ReadNumber
fld qword [number_in]
.return:
pop eax
pop ebx
pop esi
popfd
ret
;----------------
; WriteChar
; Vypise znak ulozeny v registru AL
;
WriteChar:
push eax
push ecx
push edx
movzx ecx,al
push ecx
push format_char
invoke printf
add esp,8
pop edx
pop ecx
pop eax
ret
;----------------
; WriteNewLine
; Vypise "End Of Line", tedy ASCII hodnoty CR, LF ve Windows (13, 10) a LF v Linuxu (10)
;
WriteNewLine:
pushfd
push eax
push ecx
push edx
push msg_EOL
invoke printf
add esp,4
pop edx
pop ecx
pop eax
popfd
ret
;----------------
; Funkce WriteBinX (8, 16, 32) {WriteBin8, WriteBin16, WriteBin32}
; Vypise 8,16,32 bitu z registru AL, AX, EAX
;
WriteBin8:
pushfd
push ecx
push eax
mov ecx,8
rcl eax,24
jmp WriteBin
WriteBin16:
pushfd
push ecx
push eax
mov ecx,16
rcl eax,16
jmp WriteBin
WriteBin32:
pushfd
push ecx
push eax
mov ecx,32
WriteBin:
push edx
push ebx
push edi
push esi
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
pop esi
pop edi
pop ebx
pop edx
pop eax
pop ecx
popfd
ret
;----------------
; WriteString
; Vypise retezce ukonceneho 0 (ASCIIZ), jehoz adresa je ulozena v registru ESI
;
WriteString:
pushfd
push eax
push ecx
push edx
push esi
push format_string
invoke printf
add esp,8
pop edx
pop ecx
pop eax
popfd
ret
;----------------
; WriteFlags
; Vypise stav registru priznaku
;
WriteFlags:
pushfd
push eax
push ebx
push ecx
push edx
push esi
push edi
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
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
popfd
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:
pushfd
push eax
movsx eax,al
jmp WriteInt
WriteUInt8:
pushfd
push eax
movzx eax,al
jmp WriteUInt
WriteInt16:
pushfd
push eax
movsx eax,ax
jmp WriteInt
WriteUInt16:
pushfd
push eax
movzx eax,ax
jmp WriteUInt
WriteInt32:
pushfd
push eax
WriteInt:
push ecx
push edx
push eax
push dword format_int
invoke printf
add esp,8
pop edx
pop ecx
pop eax
popfd
ret
WriteUInt32:
pushfd
push eax
WriteUInt:
push ecx
push edx
push eax
push dword format_uint
invoke printf
add esp,8
pop edx
pop ecx
pop eax
popfd
ret
;----------------
; Funkce WriteFloat
; Vypise 32-bitove realne cislo z registru EAX
;
WriteFloat:
pushfd
push eax
push ecx
push edx
push eax
fld dword [esp]
sub esp, 4
fstp qword [esp]
push dword format_float
invoke printf ; printf vyzaduje vzdy double!
add esp,12
pop edx
pop ecx
pop eax
popfd
ret
;----------------
; Funkce WriteDouble
; Vypise 64-bitove realne cislo z registru koprocesoru ST0
;
WriteDouble:
pushfd
push eax
push ecx
push edx
sub esp,8
fst qword [esp]
push dword format_double
invoke printf
add esp,12
pop edx
pop ecx
pop eax
popfd
ret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment