# mp1.S - missile-command version .data # Constants for accessing the fields of a struct missile, # struct missile is defined in rtc.h and mp1.h NEXT = 0 X = 4 Y = 8 VX = 12 VY = 16 DEST_X = 20 DEST_Y = 24 EXPLODED = 28 C = 32 # Character to draw for an explosion - '@' EXPLOSION = 64 # Data shared between this file and rtc.c helper functions # This '.globl' directive makes these symbols visible externally .globl mp1_missile_list, base_alive, mp1_score mp1_missile_list: .long 0x0 # Head of list pointer base_alive: .long 0x0 # Array of 3 bytes, plus a padding byte mp1_score: .long 0x0 # Player's current score # Data private to this file base_pic: .string "/^^^\\" # Picture of a live base dead_base_pic: .string "xxxxx" # Picture of a dead base crosshairs_x: .long 0x0 # X-position of the crosshairs crosshairs_y: .long 0x0 # Y-position of the crosshairs .text # void mp1_poke(void); # You can use this function to write to video memory. # # Interface: Register-based arguments (not C-style) # Inputs: %cl - The byte you wish to write # %eax - Offset from the start of video memory that you wish # to write to # Outputs: Text-mode video screen is written to at location %eax with # the byte in %cl # Registers: Clobbers EDX mp1_poke: movl vmem_base_addr(,1),%edx movb %cl,(%edx,%eax,1) ret # ----------------- Exported functions --------------------- # void mp1_rtc_tasklet(unsigned long garbage); # Performs three tasks: # (1) updates the list of missiles (implement this in update_missiles, # below, and call it from here). # (2) Redraw the bases - they may have been overwritten with missiles # (3) Redraw the crosshairs - it may have been overwritten with missiles # Inputs : none # Outputs : none # Registers: Standard C calling convention .globl mp1_rtc_tasklet mp1_rtc_tasklet: # callee save pushl %ebp movl %esp, %ebp # make the three calls pushl %edx call update_missiles popl %edx pushl %edx call mp1_rtc_tasklet_redraw_bases popl %edx pushl %edx call mp1_rtc_tasklet_redraw_xhair popl %edx # callee teardown leave ret mp1_rtc_tasklet_redraw_bases: # ESI - Counter for outer loop = 3 # EDI - Counter for inner loop = 5 # EBX - Hold ptr to base # callee save pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi # redraw bases # initialize variables for the 2 loops movl $3876, %eax movl $5, %edi movl $3, %esi movl $base_alive, %edx # loop to print 5 characters mp1_rtc_tasklet_redraw_bases_outter: cmpl $0, %esi jle mp1_rtc_tasklet_redraw_bases_outter_exit cmpb $0, (%edx) je mp1_rtc_tasklet_redraw_bases_dead movl $base_pic, %ebx jmp mp1_rtc_tasklet_redraw_bases_inner mp1_rtc_tasklet_redraw_bases_dead: movl $dead_base_pic, %ebx mp1_rtc_tasklet_redraw_bases_inner: cmpl $0, %edi jle mp1_rtc_tasklet_redraw_bases_inner_exit movb (%ebx), %cl pushl %edx call mp1_poke popl %edx addl $1, %ebx addl $2, %eax decl %edi jmp mp1_rtc_tasklet_redraw_bases_inner mp1_rtc_tasklet_redraw_bases_inner_exit: addl $30, %eax # movl $base_pic, %ebx movl $5, %edi decl %esi addl $1, %edx jmp mp1_rtc_tasklet_redraw_bases_outter mp1_rtc_tasklet_redraw_bases_outter_exit: # callee teardown popl %edi popl %esi popl %ebx leave ret mp1_rtc_tasklet_redraw_xhair: # callee save pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi # redraw xhair movl crosshairs_y, %eax imull $160, %eax # 80 x 2 movl crosshairs_x, %ebx imull $2, %ebx addl %ebx, %eax movb $88, %cl call mp1_poke # callee teardown popl %edi popl %esi popl %ebx leave ret # int mp1_ioctl(unsigned long arg, unsigned int cmd) # The dispatch function for the MP1 ioctls - should use the cmd argument # and a jumptable to execute one of the specific ioctls implemented below. # Inputs : unsigned long arg - parameter to the mp1_ioctl_.... # : unsigned int cmd - specifies which mp1_ioctl_... function # : to execute # Outputs : Returns an integer - depends on which ioctl() function is called # Registers: Standard C calling convention .globl mp1_ioctl mp1_ioctl: # get cmd in eax movl 8(%esp), %eax # compare agar > 4 cmpl $4, %eax jg mp1_ioctl_invalid # compare agar < 0 cmpl $0, %eax jl mp1_ioctl_invalid # then jump to jump table jmp *jump_table(, %eax, 4) # agar invalid mp1_ioctl_invalid: movl $-1, %eax ret # ----------------- Functions private to this file ------------------- update_missiles: # callee save pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi # render the missiles # ebx is current_head movl mp1_missile_list, %ebx update_missiles_loop: cmpl $0, %ebx je update_missiles_loop_end movl %ebx, %edi # temp gets curr movl (%edi), %edi # temp gets temp next # start render cmpl $0, EXPLODED(%ebx) # NOT EXPLODING je update_missiles_not_exploding # EXPLODING pushl %edi pushl %ebx call update_missiles_exploding popl %ebx popl %edi update_missiles_not_exploding_return: movl %edi, %ebx # curr gets temp jmp update_missiles_loop update_missiles_loop_end: # callee teardown popl %edi popl %esi popl %ebx leave ret update_missiles_not_exploding: pushl %edi pushl %ebx pushl %esi # call draw with ' ' and struct ptr pushl $32 pushl %ebx call update_missiles_draw popl %ebx addl $4, %esp # add delta movl X(%ebx), %edi movl Y(%ebx), %esi addl VX(%ebx), %edi addl VY(%ebx), %esi movl %edi, X(%ebx) movl %esi, Y(%ebx) # get high 16 bits shrl $16, %edi shrl $16, %esi # check agar inside screen cmpl $79, %edi jg update_missiles_not_exploding_outside_screen cmpl $0, %edi jl update_missiles_not_exploding_outside_screen cmpl $24, %esi jg update_missiles_not_exploding_outside_screen cmpl $0, %esi jl update_missiles_not_exploding_outside_screen jmp update_missiles_not_exploding_inside_screen update_missiles_not_exploding_internal_return: popl %esi popl %ebx popl %edi jmp update_missiles_not_exploding_return update_missiles_not_exploding_inside_screen: # is at destination? cmpl DEST_X(%ebx), %edi jne update_missiles_not_exploding_inside_screen_not_at_dest cmpl DEST_Y(%ebx), %esi jne update_missiles_not_exploding_inside_screen_not_at_dest pushl %ebx call update_missiles_exploding popl %ebx jmp update_missiles_not_exploding_internal_return update_missiles_not_exploding_inside_screen_not_at_dest: pushl C(%ebx) pushl %ebx call update_missiles_draw popl %ebx addl $4, %esp jmp update_missiles_not_exploding_internal_return update_missiles_not_exploding_outside_screen: # delete from list pushl %ebx call update_missiles_delete popl %ebx jmp update_missiles_not_exploding_internal_return update_missiles_exploding: # callee save pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi # ebx gets current ptr - ask movl 8(%ebp), %ebx # call missile_explode - ask pushl %ebx call missile_explode popl %ebx # call user notifyy cmpl $0, %eax jne call_notify_user return_from_call_notify_user: # decrement EXPLODED decl EXPLODED(%ebx) # check if 0 (just 0) cmpl $0, EXPLODED(%ebx) je update_missiles_exploding_e_0 jmp update_missiles_exploding_e_not_0 update_missiles_exploding_e_0: # call draw with ' ' and struct ptr pushl $32 pushl %ebx call update_missiles_draw popl %ebx addl $4, %esp # call delete with struct ptr pushl %ebx call update_missiles_delete popl %ebx jmp update_missiles_exploding_end update_missiles_exploding_e_not_0: # call draw with @ and struct ptr pushl $EXPLOSION pushl %ebx call update_missiles_draw popl %ebx addl $4, %esp update_missiles_exploding_end: popl %edi popl %esi popl %ebx leave ret call_notify_user: call mp1_notify_user jmp return_from_call_notify_user update_missiles_draw: # callee save pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi movl 8(%ebp), %ebx # ebx gets ptr movl X(%ebx), %esi # esi gets X movl Y(%ebx), %edi # edi gets Y shrl $16, %esi # get high 16 bits from X and Y shrl $16, %edi imull $160, %edi, %eax # 80 x 2 imull $2, %esi # X = X x 2 addl %esi, %eax # eax = 160 * Y + X * 2 movb 12(%ebp), %cl # cl gets char pushl %edx call mp1_poke popl %edx popl %edi popl %esi popl %ebx leave ret update_missiles_delete: # callee save pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi # get the ptr to delete movl 8(%ebp), %ebx # get the head ptr movl mp1_missile_list, %esi # see if head == ptr cmpl %ebx, %esi je update_missiles_delete_change_head update_missiles_delete_loop: cmpl $0, %esi je update_missiles_delete_end cmpl (%esi), %ebx je update_missiles_delete_remove movl (%esi), %esi jmp update_missiles_delete_loop update_missiles_delete_end: popl %edi popl %esi popl %ebx leave ret update_missiles_delete_remove: movl (%ebx), %edi movl %edi, (%esi) pushl %ebx call mp1_free popl %ebx movl %edi, %eax jmp update_missiles_delete_end update_missiles_delete_change_head: movl (%esi), %esi movl %esi, mp1_missile_list pushl %ebx call mp1_free popl %ebx movl %esi, %eax jmp update_missiles_delete_end mp1_ioctl_startgame: # callee save pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi # movl $0, mp1_missile_list movl $0, mp1_score movl $40, crosshairs_x movl $12, crosshairs_y movb $1, base_alive movb $1, base_alive + 1 movb $1, base_alive + 2 popl %edi popl %esi popl %ebx leave ret mp1_ioctl_addmissile: # eax - return value # ebx - ptr to user space struct # edi - ptr to alloted memory for the struct in kernel # esi - temp var to help add to linked list # callee save pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi # dynamic memory allocation malloc(36) - 36 bytes (size of struct) pushl $36 call mp1_malloc addl $4, %esp # check for malloc error cmpl $0, %eax je mp1_ioctl_addmissile_malloc_error movl %eax, %edi # get user space ptr to ebx and check validity movl 8(%ebp), %ebx # getting argument cmpl $0, %ebx je mp1_ioctl_addmissile_copy_error # copy to kernel pushl $36 pushl %ebx pushl %edi call mp1_copy_from_user popl %edi popl %ebx addl $4, %esp # check for copy error cmpl $0, %eax jne mp1_ioctl_addmissile_copy_error # add to the linked list movl mp1_missile_list, %esi # temp gets head movl %esi, (%edi) movl %edi, mp1_missile_list # head gets new ptr jmp mp1_ioctl_addmissile_tear_down # free if copy error mp1_ioctl_addmissile_copy_error: pushl %edi call mp1_free addl $4, %esp # return -1 mp1_ioctl_addmissile_malloc_error: movl $-1, %eax jmp mp1_ioctl_addmissile_tear_down_with_fail # callee teardown mp1_ioctl_addmissile_tear_down: movl $0, %eax mp1_ioctl_addmissile_tear_down_with_fail: popl %edi popl %esi popl %ebx leave ret mp1_ioctl_movexhairs: # crosshairs_x # crosshairs_y # ebx - new x position # edx - new y positon # callee save pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi # check agar delta is 0 cmpl $0, 8(%ebp) je mp1_ioctl_movexhairs_return_0 # remove from current position movl crosshairs_y, %eax imull $160, %eax # 80 x 2 movl crosshairs_x, %ebx imull $2, %ebx addl %ebx, %eax movb $32, %cl call mp1_poke # caculate correct new position movl $0, %ebx movl $0, %edx addl crosshairs_x, %ebx addw 8(%ebp), %bx addl crosshairs_y, %edx addw 10(%ebp), %dx cmpl $79, %ebx jbe mp1_ioctl_movexhairs_x_up_is_ok subw 8(%ebp), %bx mp1_ioctl_movexhairs_x_up_is_ok: cmpl $0, %ebx jae mp1_ioctl_movexhairs_x_down_is_ok subw 8(%ebp), %bx mp1_ioctl_movexhairs_x_down_is_ok: cmpl $24, %edx jbe mp1_ioctl_movexhairs_y_up_is_ok subw 10(%ebp), %dx mp1_ioctl_movexhairs_y_up_is_ok: cmpl $0, %edx jae mp1_ioctl_movexhairs_y_down_is_ok subw 10(%ebp), %dx mp1_ioctl_movexhairs_y_down_is_ok: jmp mp1_ioctl_movexhairs_update_current_xhair mp1_ioctl_movexhairs_update_current_xhair: movl %ebx, crosshairs_x movl %edx, crosshairs_y mp1_ioctl_movexhairs_return_0: movl $0, %eax # callee teardown popl %edi popl %esi popl %ebx leave ret mp1_ioctl_getstatus: # esi - get param (the ptr to user space int) # edi - get my local int ptr # callee save pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi movl 8(%ebp), %esi movl $0, %ebx movw mp1_score, %bx cmpb $0, base_alive jne mp1_ioctl_getstatus_set_base1_to_alive mp1_ioctl_getstatus_base1_done: cmpb $0, base_alive + 1 jne mp1_ioctl_getstatus_set_base2_to_alive mp1_ioctl_getstatus_base2_done: cmpb $0, base_alive + 2 jne mp1_ioctl_getstatus_set_base3_to_alive jmp mp1_ioctl_getstatus_base3_done mp1_ioctl_getstatus_set_base1_to_alive: orl $0x00010000, %ebx jmp mp1_ioctl_getstatus_base1_done mp1_ioctl_getstatus_set_base2_to_alive: orl $0x00020000, %ebx jmp mp1_ioctl_getstatus_base2_done mp1_ioctl_getstatus_set_base3_to_alive: orl $0x00040000, %ebx mp1_ioctl_getstatus_base3_done: pushl %ebx movl %esp, %edi # edi is ptr to int # copy to user pushl $4 pushl %edi pushl %esi call mp1_copy_to_user popl %esi popl %edi addl $4, %esp # check for copy error cmpl $0, %eax jne mp1_ioctl_getstatus_failed # callee teardown popl %ebx popl %edi popl %esi popl %ebx movl $0, %eax leave ret # callee teardown failed mp1_ioctl_getstatus_failed: popl %ebx popl %edi popl %esi popl %ebx movl $-1, %eax leave ret mp1_ioctl_endgame: # ebx is temp # callee save pushl %ebp movl %esp, %ebp pushl %ebx pushl %esi pushl %edi mp1_ioctl_endgame_loop: cmpl $0, mp1_missile_list je mp1_ioctl_endgame_loop_end movl mp1_missile_list, %ebx # temp gets head movl mp1_missile_list, %esi movl (%esi), %esi # head gets head next movl %esi, mp1_missile_list pushl %ebx call mp1_free addl $4, %esp jmp mp1_ioctl_endgame_loop mp1_ioctl_endgame_loop_end: # callee teardown popl %edi popl %esi popl %ebx leave ret jump_table: .long mp1_ioctl_startgame, mp1_ioctl_addmissile, mp1_ioctl_movexhairs, mp1_ioctl_getstatus, mp1_ioctl_endgame
Menu