; File: ham.asm ; Programmer: Spencer Shimko ; Purpose: Calculate hamming distance of 2 strings ; ; Assemble using NASM: nasm -f elf ham.asm ; Link with ld: ld ham.o ; %define STDIN 0 %define STDOUT 1 %define SYSCALL_EXIT 1 %define SYSCALL_READ 3 %define SYSCALL_WRITE 4 %define BUFLEN 256 SECTION .data ; initialized data section msg1: db "Input string #1 (<31): " ; prompt string 1 len1: equ $-msg1 ; length of first message msg2: db "Input string #2 (<31): " ; prompt string 2 len2: equ $-msg2 ; length of second message msg3: db "Hamming Distance: " ; converted string label len3: equ $-msg3 ; length of third message msg4: db 10, "Read error", 10 ; error message len4: equ $-msg4 count: dd 0 ; hamming count SECTION .bss ; uninitialized data section str1: resb BUFLEN ; buffer for 1st string str2: resb BUFLEN ; buffer for 2nd string rlen1: resb 4 ; length of 1st string rlen2: resb 4 ; length of 2nd string SECTION .text ; Code section. global _start ; let loader see entry point _start: nop ; Entry point. start: ; address for gdb ; prompt user for input ; mov eax, SYSCALL_WRITE ; write function mov ebx, STDOUT ; Arg1: file descriptor mov ecx, msg1 ; Arg2: addr of message mov edx, len1 ; Arg3: length of message int 080h ; ask kernel to write ; read user input ; mov eax, SYSCALL_READ ; read function mov ebx, STDIN ; Arg 1: file descriptor mov ecx, str1 ; Arg 2: address of buffer mov edx, BUFLEN ; Arg 3: buffer length int 080h ; error check ; sub eax,1 ; remove the carriage return mov [rlen1], eax ; save length of string read cmp eax, 0 ; check if any chars read jg read1_OK ; >0 chars read = OK mov eax, SYSCALL_WRITE ; ow print error mesg mov ebx, STDOUT mov ecx, msg4 mov edx, len4 int 080h jmp exit ; skip over rest read1_OK: ; prompt user for input ; mov eax, SYSCALL_WRITE ; write function mov ebx, STDOUT ; Arg1: file descriptor mov ecx, msg2 ; Arg2: addr of message mov edx, len2 ; Arg3: length of message int 080h ; ask kernel to write ; read user input ; mov eax, SYSCALL_READ ; read function mov ebx, STDIN ; Arg 1: file descriptor mov ecx, str2 ; Arg 2: address of buffer mov edx, BUFLEN ; Arg 3: buffer length int 080h ; error check ; sub eax,1 ; remove the carriage return mov [rlen2], eax ; save length of string read cmp eax, 0 ; check if any chars read jg read2_OK ; >0 chars read = OK mov eax, SYSCALL_WRITE ; ow print error mesg mov ebx, STDOUT mov ecx, msg4 mov edx, len4 int 080h jmp exit ; skip over rest read2_OK: loop_Init: mov esi, str1 ; point to start of string1 mov edi, str2 ; point to start of string2 mov eax,[rlen1] ; compare string sizes mov ebx,[rlen2] ; and loop based on smallest cmp eax,ebx ; string size jg str2_Sml ; string2 is smaller jump ; string1 is smaller... mov ecx, eax ; initialize count jmp L1_test ; start the loop str2_Sml: mov ecx, ebx ; initialize count jmp L1_test ; start the loop L1_test: cmp ecx,31 ; if there are more then 31 chars jb L1_top mov ecx,31 ; fail safe L1_top: mov al, [esi] ; get a character from str1 mov bl, [edi] ; get a character from str2 inc esi ; update str1 ptr inc edi ; update str2 ptr xor al, bl ; find the different bits mov ah, 8 ; setup innerloop counter L2_top: dec ah ; decrement bit counter jz L1_cont ; get new char to ham every ; 8 bits shr al,1 ; rotate string1 jc Bit_on ; bit is on jmp L2_top ; bit is off so re-loop Bit_on: ; we have a different bit inc dword [count] ; inc ham count jmp L2_top ; cont loop L1_cont: dec ecx ; update char count jnz L1_top ; loop to top if more chars ; final exit ; exit: mov EAX, SYSCALL_EXIT ; exit function mov EBX, [count] ; exit code = hamming distance int 080h ; ask kernel to take over