#---------------------------------------------------------------- # Program LAB_4.S - Architektury Komputerów #---------------------------------------------------------------- # # To compile: as -o lab_4.o lab_4.s # To link: ld -o lab_4 lab_4.o # To run: ./lab_4 # #---------------------------------------------------------------- .equ write_64, 1 .equ exit_64, 60 .equ stdout, 1 #---------------------------------------------------------------- .data vector: # vector of items .long 10,70,50,90,60,80,40,20,0,30,98,78 count: # count of items .quad ( . - vector ) >> 2 item: .string "Item " line_no: .string " " itemval: .string " = " number: .string " \n" FL_text: .string "\nFrom first to last:\n" LF_text: .string "\nFrom last to first:\n" dataend: .equ item_len, FL_text - item .equ FL_len, LF_text - FL_text .equ LF_len, dataend - LF_text #---------------------------------------------------------------- .text .global _start .macro disp_str_64 file_id, address, length mov $write_64, %rax mov \file_id, %rdi mov \address, %rsi mov \length, %rdx syscall .endm .macro exit_prog_64 exit_code mov $exit_64, %rax mov \exit_code, %rdi syscall .endm #---------------------------------------------------------------- _start: disp_str_64 $stdout, $FL_text, $FL_len # display message CALL disp_vector_FL # display content of vector disp_str_64 $stdout, $LF_text, $LF_len # display message CALL disp_vector_LF # display content of vector exit_prog_64 $0 # exit program #---------------------------------------------------------------- # # Function: disp_vector_FL # Parameters: none # .type disp_vector_FL,@function disp_vector_FL: MOV count,%rcx # data count XOR %rsi,%rsi # data index next_item: MOV vector(,%rsi,4),%ebx # get data CALL make_string # convert to string push %rcx push %rsi disp_str_64 $stdout, $item, $item_len # display prepared string pop %rsi pop %rcx INC %rsi # next element LOOP next_item # { rcx--; if( rcx ) goto next_item } RET # return to main program #---------------------------------------------------------------- # # Function: disp_vector_LF # Parameters: none # .type disp_vector_LF,@function disp_vector_LF: MOV count,%rcx # data count MOV %rcx,%rsi # data index DEC %rsi # data index-- prev_item: MOV vector(,%rsi,4),%ebx # get data CALL make_string # convert to string push %rcx push %rsi disp_str_64 $stdout, $item, $item_len # display prepared string pop %rsi pop %rcx DEC %rsi # previous element LOOP prev_item # { rcx--; if( rcx ) goto prev_item } RET # return to main program #---------------------------------------------------------------- # # Function: make_string # Parameters: %esi - index of element # %ebx - value of element # .type make_string,@function make_string: # MOVL $0x20202020, number MOVW $0x2020, line_no MOV %esi,%eax # convert index of vector element t MOV $line_no + 2,%rdi CALL num2dec MOV %ebx,%eax # convert value of vector element to MOV $number + 4,%rdi CALL num2dec RET # return to disp_vector function #---------------------------------------------------------------- # # Function: num2dec # Parameters: %eax - value # %rdi - address of last character # .type num2dec,@function num2dec: PUSH %rbx # save register on stack PUSH %rdx # save register on stack MOV $10,%ebx # divisor in EBX, dividend in EAX nextdig: XOR %edx,%edx # EDX = 0 DIV %ebx # EDX:EAX div EBX ADD $'0',%dl # convert remainder (in EDX) to character MOV %dl,(%rdi) # *(RDI) = character (decimal digit) CMP $0,%eax # quotient in EAX JZ empty DEC %rdi # RDI-- JMP nextdig empty: POP %rdx # restore register from stack POP %rbx # restore register from stack RET # return to make_string function #----------------------------------------------------------------