; File: report.asm ; Programmer: Spencer Shimko ; Purpose: Generate a report based on an externally ; array of records. ; ; 1. Compile records structure: gcc -c records.c ; 2. Assemble using NASM: nasm -f elf report.asm ; 3. Link with ld: ld report.o records.o ; %define STDIN 0 %define STDOUT 1 %define SYSCALL_EXIT 1 %define SYSCALL_READ 3 %define SYSCALL_WRITE 4 ; Record Address Offset %define NickOffset 32 %define AlignOffset 48 %define RoleOffset 68 %define PointsOffset 88 %define LevelOffset 92 %define RecSize 96 ; External symbols extern records, num_records SECTION .data ; initialized data section msg1: db "Lowest Points: " ; Output message 1 len1: equ $-msg1 ; length of first message msg2: db "First Nickname: " ; Output message 2 len2: equ $-msg2 ; length of second message msg3: db 10, "Array/Record Error!",10 ; error message len3: equ $-msg3 nl: db 10 ; new line len_nl: equ $-nl points: dw 0 ; low score record # alpha: dw 0 ; 1st alphabetic record # char: dw 0 ; current char for alpha SECTION .bss ; uninitialized data section res1: resb NickOffset ; Name of person with lowest pts res2: resb NickOffset ; Name of 1st alpha nick SECTION .text ; Code section. global _start ; let loader see entry point _start: nop ; Entry point. start: ; address for gdb loop_Init: mov ecx, 0 ; Record counter ; the counter starts at 0 b/c the current "winning" records ; are records #1, so basically we can skip a useless comparison ; once we increment cx at the beginging of loop_Top cmp [num_records], dword 0 jbe near exit_Error ; array of 0 records=bad loop_Top: inc cx cmp cx, [num_records] ; check record count jge near Display_Output ; out of records so jump ; get to the correct record mov ax, RecSize mul cx ; correct the 2 reg mul result mov bx,ax mov ax,dx shl eax, 16 mov ax,bx ; add the record count to the index mov edi, records add edi, eax ; get the current 1st alphabetic record mov ax, RecSize mul word [alpha] ; correct the 2 reg mul result mov bx,ax mov ax,dx shl eax, 16 mov ax, bx ; add the leading record count to the index mov esi, records add esi, eax mov [char], word 0 loop_A1: mov edx, NickOffset add edx,[char] mov al, [esi+edx] ; get a cur.1st chat mov bl, [edi+edx] ; get a character from new ; converts al chars to uppercase to make alpha easier cmp al, 'a' ; less than 'a'? jb Abl cmp al, 'z' ; more than 'z'? ja Abl and al, 11011111b ; convert to uppercase Abl: ; converts bl chars to uppercase to make alpha easier cmp bl, 'a' ; less than 'a'? jb loop_A2 cmp bl, 'z' ; more than 'z'? ja loop_A2 and bl, 11011111b ; convert to uppercase loop_A2: ; chars are now uppercase so compare cmp al, bl ; ja loop_Aswitch ; the new string should be 1st je loop_Anextchar ; the chars are the same so ; look at the nxt character jb loop_P1 ; the order is correct loop_Aswitch: mov [alpha], cx ; this record is 1st jb loop_P1 ; order is now correct loop_Anextchar: inc word [char] ; increment character ptr cmp [char], word 31 ; max chars jmp loop_P1 jmp loop_A1 ; continue alpha loop loop_P1: ; get to the points leader mov ax, RecSize mul word [points] ; correct the 2 reg mul result mov bx,ax mov ax,dx shl eax, 16 mov ax,bx ; add the record count to the index mov esi, records add esi, eax mov ebx, [edi+PointsOffset] mov eax, [esi+PointsOffset] cmp eax, ebx ; compare ja loop_Pswitch jmp loop_Top ; restart loop w/ nxt rec. loop_Pswitch: mov [points], cx ; new low points jmp loop_Top ; restart loop w/ nxt rec. Display_Output: ; display lowest points ; mov eax, SYSCALL_WRITE ; write message mov ebx, STDOUT mov ecx, msg1 mov edx, len1 int 080h mov ax, RecSize mul word [points] ; get to the "winning" record ; combine 2 reg multiplication mov bx, ax mov ax, dx shl eax, 16 mov ax, bx mov esi, res1 mov ecx, 0 L1: mov edx, eax add edx, ecx mov bl,[records+edx] cmp bl, 0 je L2 mov [esi], bl inc esi cmp cx, NickOffset-1 jae L2 inc cx jmp L1 L2: mov eax, SYSCALL_WRITE ; write message mov ebx, STDOUT mov edx, ecx ; len=counter mov ecx, res1 int 080h call print_nl ; display 1st alpha mov eax, SYSCALL_WRITE ; write message mov ebx, STDOUT mov ecx, msg2 mov edx, len2 int 080h mov ax, RecSize mul word [alpha] ; get to the "winning" record ; combine 2 reg multiplaction mov bx, ax mov ax, dx shl eax, 16 mov ax, bx mov esi, res2 mov ecx, 0 L3: mov edx, eax add edx, ecx mov bl,[records+edx] cmp bl, 0 je L4 mov [esi], bl inc esi cmp cx, NickOffset-1 jae L4 inc cx jmp L3 L4: mov eax, SYSCALL_WRITE ; write message mov ebx, STDOUT mov edx, ecx ; mov length mov ecx, res2 int 080h call print_nl jmp exit exit_Error: ; Display error and exit ; mov eax, SYSCALL_WRITE ; write function mov ebx, STDOUT ; Arg1: file descriptor mov ecx, msg3 ; Arg2: addr of message mov edx, len3 ; Arg3: length of message int 080h ; ask kernel to write mov EAX, SYSCALL_EXIT ; exit function mov EBX, 1 ; int 080h ; ask kernel to take over ; final exit ; exit: mov EAX, SYSCALL_EXIT ; exit function mov EBX, 0 int 080h ; ask kernel to take over print_nl: ; well the print subroutine online caused segfaults for me ; and i couldnt get a newline char to work at the end of the strings ; so here is a subroutine to print a newline mov eax, SYSCALL_WRITE ; write function mov ebx, STDOUT ; Arg1: file descriptor mov ecx, nl ; Arg2: addr of message mov edx, len_nl ; Arg3: length of message int 080h ; ask kernel to write ret