diff --git a/worksheet1/Makefile b/worksheet1/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..6da79074837710789dd5faab325ed66218a65721 --- /dev/null +++ b/worksheet1/Makefile @@ -0,0 +1,58 @@ +# Tools +CC = gcc +ASM = nasm +CFLAGS = -m32 +ASMFLAGS = -f elf + +# Source files +DRIVER = driver.c +ASM_SRC = task1.asm task1.2.asm task2.1.asm task2.2.asm task2.3.asm +ASM_OBJ = $(ASM_SRC:.asm=.o) +ASM_IO = asm_io.asm +ASM_IO_OBJ = asm_io.o + +# Executables +EXE1 = task1 +EXE2 = task1.2 +EXE3 = task2.1 +EXE4 = task2.2 +EXE5 = task2.3 + +# Default target +all: $(EXE1) $(EXE2) $(EXE3) $(EXE4) $(EXE5) + +# Rule for task1 +$(EXE1): $(ASM_IO_OBJ) task1.o driver.o + $(CC) $(CFLAGS) $^ -o $@ + +# Rule for task1.2 +$(EXE2): $(ASM_IO_OBJ) task1.2.o driver.o + $(CC) $(CFLAGS) $^ -o $@ + +# Rule for task2.1 +$(EXE3): $(ASM_IO_OBJ) task2.1.o driver.o + $(CC) $(CFLAGS) $^ -o $@ + +# Rule for task2.2 +$(EXE4): $(ASM_IO_OBJ) task2.2.o driver.o + $(CC) $(CFLAGS) $^ -o $@ + +# Rule for task2.3 +$(EXE5): $(ASM_IO_OBJ) task2.3.o driver.o + $(CC) $(CFLAGS) $^ -o $@ + +# Assemble asm_io.asm +$(ASM_IO_OBJ): $(ASM_IO) + $(ASM) $(ASMFLAGS) $< -o $@ + +# Assemble .asm files +%.o: %.asm + $(ASM) $(ASMFLAGS) $< -o $@ + +# Compile driver.c +driver.o: $(DRIVER) + $(CC) $(CFLAGS) -c $< -o $@ + +# Clean up build artifacts +clean: + rm -f *.o $(EXE1) $(EXE2) $(EXE3) $(EXE4) $(EXE5) diff --git a/worksheet1/Makefile.save b/worksheet1/Makefile.save new file mode 100644 index 0000000000000000000000000000000000000000..baebb6b1eabe1f8868a2ece4c89e4ec87be8c97c --- /dev/null +++ b/worksheet1/Makefile.save @@ -0,0 +1,56 @@ +# Tools +CC=gcc +ASM=nasm +CFLAGS=-m32 +ASMFLAGS=-f elf + +# Source files +DRIVER=driver.c +ASM_SRC=task1.asm task1.2.asm task2_1.asm task2_2.asm task2_3.asm +ASM_OBJ=$(ASM_SRC:.asm=.o) +ASM_IO=asm_io.asm +ASM_IO_OBJ=asm_io.o + +# Executables +EXE1=task1 +EXE2=task1.2 +EXE3=task2.1 +EXE4=task2.2 +EXE5=task2.3 + +# Default target +all: $(EXE1) $(EXE2) $(EXE3) $(EXE4) + +# Rule for task1 +$(EXE1): $(ASM_IO_OBJ) task1.o driver.o + $(CC) $(CFLAGS) $^ -o $@ + +# Rule for task1.2 $(EXE2): $(ASM_IO_OBJ) task1.2.o driver.o $(CC) $(CFLAGS) $^ -o $@ + +# Rule for task2_1 +$(EXE2): $(ASM_IO_OBJ) task2_1.o driver.o + $(CC) $(CFLAGS) $^ -o $@ + +# Rule for task2_2 +$(EXE3): $(ASM_IO_OBJ) task2_2.o driver.o + $(CC) $(CFLAGS) $^ -o $@ + +# Rule for task2_3 +$(EXE4): $(ASM_IO_OBJ) task2_3.o driver.o + $(CC) $(CFLAGS) $^ -o $@ + +# Assemble asm_io.asm +$(ASM_IO_OBJ): $(ASM_IO) + $(ASM) $(ASMFLAGS) $< -o $@ + +# Assemble .asm files +%.o: %.asm + $(ASM) $(ASMFLAGS) $< -o $@ + +# Compile driver.c +driver.o: $(DRIVER) + $(CC) $(CFLAGS) -c $< -o $@ + +# Clean up build artifacts +clean: + rm -f *.o $(EXE1) $(EXE2) $(EXE3) $(EXE4) diff --git a/worksheet1/asm_io.asm b/worksheet1/asm_io.asm new file mode 100644 index 0000000000000000000000000000000000000000..ad52628a8c8d8660a16e358d2e282ec49252d599 --- /dev/null +++ b/worksheet1/asm_io.asm @@ -0,0 +1,502 @@ +; +; file: asm_io.asm +; Assembly I/O routines +; To assemble for DJGPP +; nasm -f coff -d COFF_TYPE asm_io.asm +; To assemble for Borland C++ 5.x +; nasm -f obj -d OBJ_TYPE asm_io.asm +; To assemble for Microsoft Visual Studio +; nasm -f win32 -d COFF_TYPE asm_io.asm +; To assemble for Linux +; nasm -f elf -d ELF_TYPE asm_io.asm +; To assemble for Watcom +; nasm -f obj -d OBJ_TYPE -d WATCOM asm_io.asm +; IMPORTANT NOTES FOR WATCOM +; The Watcom compiler's C library does not use the +; standard C calling convention. For example, the +; putchar() function gets its argument from the +; the value of EAX, not the stack. + + +%define NL 10 +%define CF_MASK 00000001h +%define PF_MASK 00000004h +%define AF_MASK 00000010h +%define ZF_MASK 00000040h +%define SF_MASK 00000080h +%define DF_MASK 00000400h +%define OF_MASK 00000800h + + +; +; Linux C doesn't put underscores on labels +; +; %ifdef ELF_TYPE +%define _scanf scanf +%define _printf printf +%define _getchar getchar +%define _putchar putchar +; %endif + +; ; +; ; Watcom puts underscores at end of label +; ; +; %ifdef WATCOM +; %define _scanf scanf_ +; %define _printf printf +; %define _getchar getchar_ +; %define _putchar putchar_ +; %endif + +%ifdef OBJ_TYPE +segment .data public align=4 class=data use32 +%else +segment .data +%endif + +int_format db "%i", 0 +string_format db "%s", 0 +reg_format db "Register Dump # %d", NL + db "EAX = %.8X EBX = %.8X ECX = %.8X EDX = %.8X", NL + db "ESI = %.8X EDI = %.8X EBP = %.8X ESP = %.8X", NL + db "EIP = %.8X FLAGS = %.4X %s %s %s %s %s %s %s", NL + db 0 +carry_flag db "CF", 0 +zero_flag db "ZF", 0 +sign_flag db "SF", 0 +parity_flag db "PF", 0 +overflow_flag db "OF", 0 +dir_flag db "DF", 0 +aux_carry_flag db "AF", 0 +unset_flag db " ", 0 +mem_format1 db "Memory Dump # %d Address = %.8X", NL, 0 +mem_format2 db "%.8X ", 0 +mem_format3 db "%.2X ", 0 +stack_format db "Stack Dump # %d", NL + db "EBP = %.8X ESP = %.8X", NL, 0 +stack_line_format db "%+4d %.8X %.8X", NL, 0 +math_format1 db "Math Coprocessor Dump # %d Control Word = %.4X" + db " Status Word = %.4X", NL, 0 +valid_st_format db "ST%d: %.10g", NL, 0 +invalid_st_format db "ST%d: Invalid ST", NL, 0 +empty_st_format db "ST%d: Empty", NL, 0 + +; +; code is put in the _TEXT segment +; +%ifdef OBJ_TYPE +segment text public align=1 class=code use32 +%else +segment .text +%endif + global read_int, print_int, print_string, read_char + global print_char, print_nl, sub_dump_regs, sub_dump_mem + global sub_dump_math, sub_dump_stack + extern _scanf, _printf, _getchar, _putchar + +read_int: + enter 4,0 + pusha + pushf + + lea eax, [ebp-4] + push eax + push dword int_format + call _scanf + pop ecx + pop ecx + + popf + popa + mov eax, [ebp-4] + leave + ret + +print_int: + enter 0,0 + pusha + pushf + + push eax + push dword int_format + call _printf + pop ecx + pop ecx + + popf + popa + leave + ret + +print_string: + enter 0,0 + pusha + pushf + + push eax + push dword string_format + call _printf + pop ecx + pop ecx + + popf + popa + leave + ret + +read_char: + enter 4,0 + pusha + pushf + + call _getchar + mov [ebp-4], eax + + popf + popa + mov eax, [ebp-4] + leave + ret + +print_char: + enter 0,0 + pusha + pushf + +%ifndef WATCOM + push eax +%endif + call _putchar +%ifndef WATCOM + pop ecx +%endif + + popf + popa + leave + ret + + +print_nl: + enter 0,0 + pusha + pushf + +%ifdef WATCOM + mov eax, 10 ; WATCOM doesn't use the stack here +%else + push dword 10 ; 10 == ASCII code for \n +%endif + call _putchar +%ifndef WATCOM + pop ecx +%endif + popf + popa + leave + ret + + +sub_dump_regs: + enter 4,0 + pusha + pushf + mov eax, [esp] ; read FLAGS back off stack + mov [ebp-4], eax ; save flags + +; +; show which FLAGS are set +; + test eax, CF_MASK + jz cf_off + mov eax, carry_flag + jmp short push_cf +cf_off: + mov eax, unset_flag +push_cf: + push eax + + test dword [ebp-4], PF_MASK + jz pf_off + mov eax, parity_flag + jmp short push_pf +pf_off: + mov eax, unset_flag +push_pf: + push eax + + test dword [ebp-4], AF_MASK + jz af_off + mov eax, aux_carry_flag + jmp short push_af +af_off: + mov eax, unset_flag +push_af: + push eax + + test dword [ebp-4], ZF_MASK + jz zf_off + mov eax, zero_flag + jmp short push_zf +zf_off: + mov eax, unset_flag +push_zf: + push eax + + test dword [ebp-4], SF_MASK + jz sf_off + mov eax, sign_flag + jmp short push_sf +sf_off: + mov eax, unset_flag +push_sf: + push eax + + test dword [ebp-4], DF_MASK + jz df_off + mov eax, dir_flag + jmp short push_df +df_off: + mov eax, unset_flag +push_df: + push eax + + test dword [ebp-4], OF_MASK + jz of_off + mov eax, overflow_flag + jmp short push_of +of_off: + mov eax, unset_flag +push_of: + push eax + + push dword [ebp-4] ; FLAGS + mov eax, [ebp+4] + sub eax, 10 ; EIP on stack is 10 bytes ahead of orig + push eax ; EIP + lea eax, [ebp+12] + push eax ; original ESP + push dword [ebp] ; original EBP + push edi + push esi + push edx + push ecx + push ebx + push dword [ebp-8] ; original EAX + push dword [ebp+8] ; # of dump + push dword reg_format + call _printf + add esp, 76 + popf + popa + leave + ret 4 + +sub_dump_stack: + enter 0,0 + pusha + pushf + + lea eax, [ebp+20] + push eax ; original ESP + push dword [ebp] ; original EBP + push dword [ebp+8] ; # of dump + push dword stack_format + call _printf + add esp, 16 + + mov ebx, [ebp] ; ebx = original ebp + mov eax, [ebp+16] ; eax = # dwords above ebp + shl eax, 2 ; eax *= 4 + add ebx, eax ; ebx = & highest dword in stack to display + mov edx, [ebp+16] + mov ecx, edx + add ecx, [ebp+12] + inc ecx ; ecx = # of dwords to display + +stack_line_loop: + push edx + push ecx ; save ecx & edx + + push dword [ebx] ; value on stack + push ebx ; address of value on stack + mov eax, edx + sal eax, 2 ; eax = 4*edx + push eax ; offset from ebp + push dword stack_line_format + call _printf + add esp, 16 + + pop ecx + pop edx + + sub ebx, 4 + dec edx + loop stack_line_loop + + popf + popa + leave + ret 12 + + +sub_dump_mem: + enter 0,0 + pusha + pushf + + push dword [ebp+12] + push dword [ebp+16] + push dword mem_format1 + call _printf + add esp, 12 + mov esi, [ebp+12] ; address + and esi, 0FFFFFFF0h ; move to start of paragraph + mov ecx, [ebp+8] + inc ecx +mem_outer_loop: + push ecx + push esi + push dword mem_format2 + call _printf + add esp, 8 + + xor ebx, ebx +mem_hex_loop: + xor eax, eax + mov al, [esi + ebx] + push eax + push dword mem_format3 + call _printf + add esp, 8 + inc ebx + cmp ebx, 16 + jl mem_hex_loop + + mov eax, '"' + call print_char + xor ebx, ebx +mem_char_loop: + xor eax, eax + mov al, [esi+ebx] + cmp al, 32 + jl non_printable + cmp al, 126 + jg non_printable + jmp short mem_char_loop_continue +non_printable: + mov eax, '?' +mem_char_loop_continue: + call print_char + + inc ebx + cmp ebx, 16 + jl mem_char_loop + + mov eax, '"' + call print_char + call print_nl + + add esi, 16 + pop ecx + loop mem_outer_loop + + popf + popa + leave + ret 12 + +; function sub_dump_math +; prints out state of math coprocessor without modifying the coprocessor +; or regular processor state +; Parameters: +; dump number - dword at [ebp+8] +; Local variables: +; ebp-108 start of fsave buffer +; ebp-116 temp double +; Notes: This procedure uses the Pascal convention. +; fsave buffer structure: +; ebp-108 control word +; ebp-104 status word +; ebp-100 tag word +; ebp-80 ST0 +; ebp-70 ST1 +; ebp-60 ST2 ... +; ebp-10 ST7 +; +sub_dump_math: + enter 116,0 + pusha + pushf + + fsave [ebp-108] ; save coprocessor state to memory + mov eax, [ebp-104] ; status word + and eax, 0FFFFh + push eax + mov eax, [ebp-108] ; control word + and eax, 0FFFFh + push eax + push dword [ebp+8] + push dword math_format1 + call _printf + add esp, 16 +; +; rotate tag word so that tags in same order as numbers are +; in the stack +; + mov cx, [ebp-104] ; ax = status word + shr cx, 11 + and cx, 7 ; cl = physical state of number on stack top + mov bx, [ebp-100] ; bx = tag word + shl cl,1 ; cl *= 2 + ror bx, cl ; move top of stack tag to lowest bits + + mov edi, 0 ; edi = stack number of number + lea esi, [ebp-80] ; esi = address of ST0 + mov ecx, 8 ; ecx = loop counter +tag_loop: + push ecx + mov ax, 3 + and ax, bx ; ax = current tag + or ax, ax ; 00 -> valid number + je valid_st + cmp ax, 1 ; 01 -> zero + je zero_st + cmp ax, 2 ; 10 -> invalid number + je invalid_st + push edi ; 11 -> empty + push dword empty_st_format + call _printf + add esp, 8 + jmp short cont_tag_loop +zero_st: + fldz + jmp short print_real +valid_st: + fld tword [esi] +print_real: + fstp qword [ebp-116] + push dword [ebp-112] + push dword [ebp-116] + push edi + push dword valid_st_format + call _printf + add esp, 16 + jmp short cont_tag_loop +invalid_st: + push edi + push dword invalid_st_format + call _printf + add esp, 8 +cont_tag_loop: + ror bx, 2 ; mov next tag into lowest bits + inc edi + add esi, 10 ; mov to next number on stack + pop ecx + loop tag_loop + + frstor [ebp-108] ; restore coprocessor state + popf + popa + leave + ret 4 diff --git a/worksheet1/asm_io.inc b/worksheet1/asm_io.inc new file mode 100644 index 0000000000000000000000000000000000000000..7e54cd28fad7c4eedcf6bd7caeed2e782d87c06c --- /dev/null +++ b/worksheet1/asm_io.inc @@ -0,0 +1,30 @@ + extern read_int, print_int, print_string + extern read_char, print_char, print_nl + extern sub_dump_regs, sub_dump_mem, sub_dump_math, sub_dump_stack + +%macro dump_regs 1 + push dword %1 + call sub_dump_regs +%endmacro + + +; +; usage: dump_mem label, start-address, # paragraphs +%macro dump_mem 3 + push dword %1 + push dword %2 + push dword %3 + call sub_dump_mem +%endmacro + +%macro dump_math 1 + push dword %1 + call sub_dump_math +%endmacro + +%macro dump_stack 3 + push dword %3 + push dword %2 + push dword %1 + call sub_dump_stack +%endmacro diff --git a/worksheet1/asm_io.o b/worksheet1/asm_io.o new file mode 100644 index 0000000000000000000000000000000000000000..d2921f0c774600089db73d581638199c58d10228 Binary files /dev/null and b/worksheet1/asm_io.o differ diff --git a/worksheet1/driver.c b/worksheet1/driver.c new file mode 100644 index 0000000000000000000000000000000000000000..4178cc823b8eb5028eb2b0d50b037d56fa86f914 --- /dev/null +++ b/worksheet1/driver.c @@ -0,0 +1,8 @@ +int __attribute__((cdecl)) asm_main(void); + +int main() { + int ret_status; + ret_status = asm_main(); + return ret_status; +} + diff --git a/worksheet1/driver.o b/worksheet1/driver.o new file mode 100644 index 0000000000000000000000000000000000000000..d9c964d5c502ff05525b278dcc90cc8150982da0 Binary files /dev/null and b/worksheet1/driver.o differ diff --git a/worksheet1/task1 b/worksheet1/task1 new file mode 100755 index 0000000000000000000000000000000000000000..f39eb32490de6c8641d31af45e1500dab923d7ab Binary files /dev/null and b/worksheet1/task1 differ diff --git a/worksheet1/task1.2 b/worksheet1/task1.2 new file mode 100755 index 0000000000000000000000000000000000000000..a5c0595114b7219bd8618a06ac65335deb737ea1 Binary files /dev/null and b/worksheet1/task1.2 differ diff --git a/worksheet1/task1.2.asm b/worksheet1/task1.2.asm new file mode 100644 index 0000000000000000000000000000000000000000..d4be5e15738c256fb742b2be79b9ddeb05765ec3 --- /dev/null +++ b/worksheet1/task1.2.asm @@ -0,0 +1,50 @@ +%include "asm_io.inc" + +segment .data + msg1 db "Enter a number: ", 0 + msg2 db "The sum of ", 0 + msg3 db " and ", 0 + msg4 db " is: ", 0 + +segment .bss + integer1 resd 1 ; first integer + integer2 resd 1 ; second integer + result resd 1 ; result + +segment .text +global asm_main +asm_main: + pusha + mov eax, msg1 ; display message to enter first number + call print_string + call read_int ; read first number + mov [integer1], eax ; store first number + + mov eax, msg1 ; display message to enter second number + call print_string + call read_int ; read second number + mov [integer2], eax ; store second number + + mov eax, [integer1] ; load first integer + add eax, [integer2] ; add second integer + mov [result], eax ; store the result + + mov eax, msg2 ; display "The sum of " + call print_string + mov eax, [integer1] ; print first number + call print_int + + mov eax, msg3 ; display " and " + call print_string + mov eax, [integer2] ; print second number + call print_int + + mov eax, msg4 ; display " is: " + call print_string + mov eax, [result] ; print result + call print_int + call print_nl ; print newline + + popa + mov eax, 0 + ret diff --git a/worksheet1/task1.2.o b/worksheet1/task1.2.o new file mode 100644 index 0000000000000000000000000000000000000000..470bbe54626ceb0d4a953892543b35c7f2fd871a Binary files /dev/null and b/worksheet1/task1.2.o differ diff --git a/worksheet1/task1.asm b/worksheet1/task1.asm new file mode 100644 index 0000000000000000000000000000000000000000..09642f4d137679c307dfd72dc5523a8554c3eb88 --- /dev/null +++ b/worksheet1/task1.asm @@ -0,0 +1,26 @@ +%include "asm_io.inc" + +segment .data +integer1 dd 15 ; First integer +integer2 dd 6 ; Second integer + +segment .bss +result resd 1 ; Space for result + +segment .text +global asm_main + +asm_main: + pusha ; Save all general-purpose registers + + mov eax, [integer1] ; Load the first integer into EAX + add eax, [integer2] ; Add the second integer to EAX + mov [result], eax ; Store the result in the 'result' variable + + push eax ; Push the result onto the stack (for print_int) + call print_int ; Print the result + add esp, 4 ; Clean up the stack after print_int call + + popa ; Restore all general-purpose registers + mov eax, 0 ; Set return value to 0 (success) + ret ; Return to the caller diff --git a/worksheet1/task1.o b/worksheet1/task1.o new file mode 100644 index 0000000000000000000000000000000000000000..3dfdfb0369c09542c33888b7084a0e2ec9127781 Binary files /dev/null and b/worksheet1/task1.o differ diff --git a/worksheet1/task2.1 b/worksheet1/task2.1 new file mode 100755 index 0000000000000000000000000000000000000000..30b72b1abf98fd16214c9a90cd6edfb379137b4c Binary files /dev/null and b/worksheet1/task2.1 differ diff --git a/worksheet1/task2.1.asm b/worksheet1/task2.1.asm new file mode 100644 index 0000000000000000000000000000000000000000..da587753fb819359f711f245ade48f8639f7057b --- /dev/null +++ b/worksheet1/task2.1.asm @@ -0,0 +1,82 @@ +segment .data + name_prompt db "Enter your name: ", 0 + input_format db "%s", 0 + greeting_msg db "Welcome, %s!", 0 + newline_char db 10, 0 + count_prompt_msg db "Enter the number of times to print the welcome message: ", 0 + count_input_format db "%d", 0 + error_msg db "The number must be greater than 50 and less than 100!", 0 + +segment .bss + user_name resb 50 ; Allocate 50 bytes for the user's name + loop_count resd 1 ; Allocate 4 bytes for the loop count + +segment .text + extern printf + extern scanf + global asm_main + +asm_main: + ; Prompt the user to enter their name + push name_prompt + call printf + add esp, 4 + + ; Read the user's name + push user_name ; Address of the buffer for name + push input_format ; Format specifier "%s" + call scanf + add esp, 8 + + ; Prompt the user to enter the loop count + push count_prompt_msg + call printf + add esp, 4 + + ; Read the loop count + push loop_count ; Address of the buffer for count + push count_input_format ; Format specifier "%d" + call scanf + add esp, 8 + + ; Validate the loop count (must be between 51 and 99 inclusive) + mov eax, [loop_count] + cmp eax, 50 + jle invalid_input ; If count ≤ 50, go to error handling + cmp eax, 100 + jge invalid_input ; If count ≥ 100, go to error handling + + ; Initialize loop counter + mov ebx, [loop_count] ; Set ebx to the loop count + +print_loop: + ; Print the greeting message followed by the user's name + push user_name + push greeting_msg + call printf + add esp, 8 + + ; Decrement the counter and repeat if not zero + dec ebx + jnz print_loop + + ; Print a newline after the loop ends + push newline_char + call printf + add esp, 4 + + ; Exit the program (Linux syscall) + mov eax, 1 ; System call: exit + xor ebx, ebx ; Exit code 0 + int 0x80 + +invalid_input: + ; Handle invalid input by displaying an error message + push error_msg + call printf + add esp, 4 + + ; Exit the program with code 0 + mov eax, 1 ; System call: exit + xor ebx, ebx ; Exit code 0 + int 0x80 diff --git a/worksheet1/task2.1.o b/worksheet1/task2.1.o new file mode 100644 index 0000000000000000000000000000000000000000..3a0dd4db561a38575c12892bf78a1690b6abab7b Binary files /dev/null and b/worksheet1/task2.1.o differ diff --git a/worksheet1/task2.2 b/worksheet1/task2.2 new file mode 100755 index 0000000000000000000000000000000000000000..b84c6d049dc62b1504d9e46f515ce5a840774455 Binary files /dev/null and b/worksheet1/task2.2 differ diff --git a/worksheet1/task2.2.asm b/worksheet1/task2.2.asm new file mode 100644 index 0000000000000000000000000000000000000000..64045451335de41a63bf6242153aff0dd4bb9e03 --- /dev/null +++ b/worksheet1/task2.2.asm @@ -0,0 +1,43 @@ +section .data + result_msg db "Sum of array: %d", 10, 0 + +section .bss + array resd 100 + sum resd 1 + +section .text + global asm_main ; Change from `main` to `asm_main` + extern printf + +asm_main: + ; Initialize array + mov ecx, 0 +init_loop: + mov eax, ecx + inc eax + mov [array + ecx*4], eax + inc ecx + cmp ecx, 100 + jl init_loop + + ; Sum array + xor ecx, ecx + xor eax, eax +sum_loop: + add eax, [array + ecx*4] + inc ecx + cmp ecx, 100 + jl sum_loop + mov [sum], eax + + ; Print result + push dword [sum] + push result_msg + call printf + add esp, 8 + + ; Exit + mov eax, 1 + xor ebx, ebx + int 0x80 + diff --git a/worksheet1/task2.2.o b/worksheet1/task2.2.o new file mode 100644 index 0000000000000000000000000000000000000000..8db1ee17160b0421236ac946e001b5c191df21b7 Binary files /dev/null and b/worksheet1/task2.2.o differ diff --git a/worksheet1/task2.3 b/worksheet1/task2.3 new file mode 100755 index 0000000000000000000000000000000000000000..638c8ca714c1d8c94ebcb1583aec3f1b9302a375 Binary files /dev/null and b/worksheet1/task2.3 differ diff --git a/worksheet1/task2.3.asm b/worksheet1/task2.3.asm new file mode 100644 index 0000000000000000000000000000000000000000..4c4fb13a58268e98c58bcea6efcb3bbbc878e760 --- /dev/null +++ b/worksheet1/task2.3.asm @@ -0,0 +1,95 @@ +%include "asm_io.inc" + +segment .data + prompt_start db "Enter start of index(0-99): ", 0 + prompt_end db "Enter end index: ", 0 + range_error db "Invalid range. Please try again.", 0 + sum_msg db "The sum of the range is: ", 0 + +segment .bss + array resd 100 + start_range resd 1 + end_range resd 1 + sum_result resd 1 + +segment .text +global asm_main +asm_main: + pusha + + ; Initialize array with values 1 to 100 + mov ecx, 100 ; Counter for 100 elements + mov esi, array ; Point to start of array + mov eax, 1 ; Initial value to store + +init_loop: + mov [esi], eax ; Store value in array + add esi, 4 ; Move to next element (4 bytes per int) + inc eax ; Increment value + loop init_loop + +get_input: + ; Get start of range + mov eax, prompt_start + call print_string + call read_int + mov [start_range], eax + + ; Get end of range + mov eax, prompt_end + call print_string + call read_int + mov [end_range], eax + + ; Validate range + mov eax, [start_range] + mov ebx, [end_range] + cmp eax, ebx + jg invalid_range ; Start > End + cmp eax, 1 + jl invalid_range ; Start < 1 + cmp ebx, 100 + jg invalid_range ; End > 100 + + ; Adjust indices to zero-based + dec eax ; Start index -= 1 + dec ebx ; End index -= 1 + mov [start_range], eax + mov [end_range], ebx + + ; Sum the range + xor eax, eax ; Clear sum (eax = 0) + mov ecx, [start_range] ; Start index + mov edx, [end_range] ; End index + mov esi, array ; Point to array base + +sum_range_loop: + add eax, [esi + ecx * 4] ; Add array[ecx] to sum + inc ecx ; Move to next index + cmp ecx, edx ; Check if we've reached the end + jg sum_done ; Exit if ecx > end + + jmp sum_range_loop ; Repeat loop + +sum_done: + mov [sum_result], eax ; Store result in sum_result + + ; Print result + mov eax, sum_msg + call print_string + mov eax, [sum_result] + call print_int + call print_nl + + jmp end_program + +invalid_range: + mov eax, range_error + call print_string + call print_nl + jmp get_input ; Retry input + +end_program: + popa + mov eax, 0 + ret diff --git a/worksheet1/task2.3.o b/worksheet1/task2.3.o new file mode 100644 index 0000000000000000000000000000000000000000..c34d0774221320472ba8fdd2693ffdf9e65777f8 Binary files /dev/null and b/worksheet1/task2.3.o differ diff --git a/worksheet2/Makefile b/worksheet2/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..17421642cba7df7fbf014372dc0956cf25c92aa9 --- /dev/null +++ b/worksheet2/Makefile @@ -0,0 +1,74 @@ +# Makefile for building and running the OS kernel + +# Directories +dirs = drivers source iso iso/boot iso/boot/grub + +# Files +kernel = iso/boot/kernel.elf +iso_image = os.iso +loader = source/loader.asm +loader_obj = source/loader.o +linker_script = source/link.ld +menu_lst = iso/boot/grub/menu.lst +stage2_file = /opt/os/stage2_eltorito +log_file = logQ.txt + +# Compiler and tools +NASM = nasm +LD = ld +QEMU = qemu-system-i386 +GENISOIMAGE = genisoimage + +# Flags +NASM_FLAGS = -f elf +LD_FLAGS = -T $(linker_script) -melf_i386 +GENISO_FLAGS = -R \ + -b boot/grub/stage2_eltorito \ + -no-emul-boot \ + -boot-load-size 4 \ + -A os \ + -input-charset utf8 \ + -quiet \ + -boot-info-table +QEMU_FLAGS = -nographic -boot d -cdrom $(iso_image) -m 32 -d cpu -D $(log_file) + +# Targets +.PHONY: all clean run + +all: $(dirs) $(iso_image) + +# Create required directories +$(dirs): + mkdir -p $@ + +# Build loader object file +$(loader_obj): $(loader) + $(NASM) $(NASM_FLAGS) -o $@ $< + +# Build the kernel +$(kernel): $(loader_obj) $(linker_script) + $(LD) $(LD_FLAGS) $(loader_obj) -o $@ + +# Copy files to GRUB directory +iso/boot/grub/stage2_eltorito: + cp $(stage2_file) $@ + +$(menu_lst): + echo "default=0" > $@ + echo "timeout=0" >> $@ + echo "title os" >> $@ + echo "kernel /boot/kernel.elf" >> $@ + +# Build the ISO image +$(iso_image): iso/boot/grub/stage2_eltorito $(menu_lst) $(kernel) + $(GENISOIMAGE) $(GENISO_FLAGS) -o $@ iso + +# Run the OS in QEMU +run: $(iso_image) + $(QEMU) $(QEMU_FLAGS) + +# Clean up generated files +clean: + rm -rf source/loader.o $(iso_image) $(log_file) + rm -rf iso/boot/kernel.elf iso/boot/grub/stage2_eltorito $(menu_lst) + rmdir --ignore-fail-on-non-empty $(dirs) diff --git a/worksheet2/iso/boot/grub/menu.lst b/worksheet2/iso/boot/grub/menu.lst new file mode 100644 index 0000000000000000000000000000000000000000..5ae00955b631e360144305e29725b1d142f96c62 --- /dev/null +++ b/worksheet2/iso/boot/grub/menu.lst @@ -0,0 +1,4 @@ +default=0 +timeout=0 +title os +kernel /boot/kernel.elf diff --git a/worksheet2/iso/boot/grub/stage2_eltorito b/worksheet2/iso/boot/grub/stage2_eltorito new file mode 100644 index 0000000000000000000000000000000000000000..9e1617cee78bb8f1ab6838837c9a1f36d729c9fd Binary files /dev/null and b/worksheet2/iso/boot/grub/stage2_eltorito differ diff --git a/worksheet2/iso/boot/kernel.elf b/worksheet2/iso/boot/kernel.elf new file mode 100755 index 0000000000000000000000000000000000000000..18e16939683d0011afd371865e03a36acbf5329b Binary files /dev/null and b/worksheet2/iso/boot/kernel.elf differ diff --git a/worksheet2/logQ.txt b/worksheet2/logQ.txt new file mode 100644 index 0000000000000000000000000000000000000000..3d414e6b84d134a05a7714e42f80b8a2b9da53e2 Binary files /dev/null and b/worksheet2/logQ.txt differ diff --git a/worksheet2/os.iso b/worksheet2/os.iso new file mode 100644 index 0000000000000000000000000000000000000000..ac5b26130c24dd23156212e0573854e2ed4a8018 Binary files /dev/null and b/worksheet2/os.iso differ diff --git a/worksheet2/source/kernel.c b/worksheet2/source/kernel.c new file mode 100644 index 0000000000000000000000000000000000000000..49fb14f2dfb3c782b6eef149a3434580ed90537a --- /dev/null +++ b/worksheet2/source/kernel.c @@ -0,0 +1,11 @@ +int sum_of_three(int a, int b, int c) { + return a + b + c; +} + +int multiply(int a, int b) { + return a * b; +} + +int subtract(int a, int b) { + return a - b; +} diff --git a/worksheet2/source/link.ld b/worksheet2/source/link.ld new file mode 100644 index 0000000000000000000000000000000000000000..ed14d2a7df5d30c4468f43ef67e4ea68084bc5a7 --- /dev/null +++ b/worksheet2/source/link.ld @@ -0,0 +1,9 @@ +ENTRY(loader) + +SECTIONS { + . = 0x00100000; + .text ALIGN (0x1000) : { *(.text) } + .rodata ALIGN (0x1000) : { *(.rodata*) } + .data ALIGN (0x1000) : { *(.data) } + .bss ALIGN (0x1000) : { *(COMMON) *(.bss) } +} diff --git a/worksheet2/source/loader.asm b/worksheet2/source/loader.asm new file mode 100644 index 0000000000000000000000000000000000000000..0a7d3c37003169e7296c7806d1b21e1d89d9c174 --- /dev/null +++ b/worksheet2/source/loader.asm @@ -0,0 +1,18 @@ +global loader ; The entry symbol for the ELF file + +; Define constants for multiboot +MAGIC_NUMBER equ 0x1BADB002 ; Multiboot magic number +FLAGS equ 0x0 ; Multiboot flags +CHECKSUM equ -(MAGIC_NUMBER) ; Checksum (magic number + flags + checksum = 0) + +section .text +align 4 ; Align to 4 bytes +dd MAGIC_NUMBER ; Write the magic number +dd FLAGS ; Write the flags +dd CHECKSUM ; Write the checksum + +loader: ; Entry point (defined in link.ld) + mov eax, 0xCAFEBABE ; Place the value in EAX +.loop: + jmp .loop ; Infinite loop + diff --git a/worksheet2/source/loader.o b/worksheet2/source/loader.o new file mode 100644 index 0000000000000000000000000000000000000000..dfcbed2f3a4c859a2a16476a9016f153df56d614 Binary files /dev/null and b/worksheet2/source/loader.o differ