%include "asm_io.inc" segment .data string db "I REALLY HATE WRITING ASSEMBLY CODE", 0 msg db ": ",0 segment .bss segment .text global asm_main asm_main: enter 0,0 ; setup pusha ; setup ;;; Main program ;;; push string ; push the argument to print_tallies call print_tallies ; call print_tallies add esp, 4 ; remove the argument from the stack jmp end ; go to the end of the program ;;; print_tallies function ;;; ;;; arguments: 1 4-byte address ;;; local variables: a 26-element single word array (52 bytes) print_tallies: push ebp ; save ebp mov ebp, esp ; set ebp to esp sub esp, 52 ; add stack space for 52 bytes! ;;; initialize tally array mov ecx, ebp ; set ecx to ebp sub ecx, 52 ; set ecx to the @ of the first tally init_loop: mov word [ecx], 0 ; set the current tally to 0 add ecx, 2 ; ecx += 2 (move on to the next tally) cmp ecx, ebp ; if reached the end of the tallies, stop jnz init_loop ; otherwise keep looping ;;; compute the tallies mov ebx, [ebp+8] ; set ebx to the first character of the string argument tally_loop: cmp byte [ebx], 0 ; is the current byte null? jz end_tally_loop ; if so, exit the loop mov al, [ebx] ; load the byte into al sub al, 65 ; subtract the ASCII code for 'A' mov ecx, ebp ; set ecx to ebp sub ecx, 52 ; set ecx to the address of the first tally shl al, 1 ; multiply al by two movzx eax, al ; zero extend al into eax add ecx, eax ; add eax to ecx, so that ecx points to the right tally inc dword [ecx] ; increment the tally inc ebx ; increment ebx to point to the next byte jmp tally_loop ; loop end_tally_loop: ;;; print the tallies mov ecx, ebp ; set ecx to ebp sub ecx, 52 ; set ecx to the address of the first tally mov bl, 65 ; set bl to the ASCII code for 'A' print_tally_loop: movzx eax, bl ; print the current character call print_char ; print the current character mov eax, msg ; print ": " call print_string ; print ": " mov ax, [ecx] ; ax = current tally movzx eax, ax ; zero extend the tally call print_int ; print the tally call print_nl ; print a new line inc bl ; increment bl add ecx, 2 ; ecx points to the next tally cmp ecx, ebp ; if not beyond the last tally jnz print_tally_loop ; keep looping mov esp, ebp ; clean up the stack! pop ebp ; restore ebp ret ; return end: popa ; cleanup mov eax, 0 ; cleanup leave ; cleanup ret ; cleanup