.text .global set_batt_from_ports # # ENTRY POINT FOR REQUIRED FUNCTION # # a useful technique for this problem # movX SOME_GLOBAL_VAR(%rip), %reg # load global variable into register # Check the C type of the variable # char / short / int / long # and use one of # movb / movw / movl / movq # and appropriately sized destination register set_batt_from_ports: # checks for positive voltage cmpw $0, BATT_VOLTAGE_PORT(%rip) # compares volts with zero jl return_one # if negative, returns 1, fail # calculating mvolts movq $0, %rdx # clears register movw BATT_VOLTAGE_PORT(%rip), %dx # moves batt voltage port into rdx register sarw $1, %dx # conversion to mvolts movw %dx, 0(%rdi) # sets mvolts # mvolts bounds checking cmpw $3000, %dx # comparing mvolts with 3000 jle line_37_check # if mvolts less than 3000, jmps to set percent to zero # calculating batt percent # batt->percent = (batt->mlvolts - 3000) >> 3; subw $3000, %dx # subtracting 3000 from mvolts sarw $3, %dx # shifting ^^ to the right by 3 andw $0xFF, %dx movb %dl, 2(%rdi) # sets percent jmp_back_37: # after setting percent above, jump here after setting percent to zero to continue # bounds checking movb 2(%rdi), %sil # gets percent and moves it into sil cmpb $100, %sil # compares with one hundred jg line_38_check # jumps if greater than 100 to set to 100 (cap) jmp_back_38: # jumps back after setting percent to 100 # creates mask for checking bit movb $1, %cl # sets cl to one salb $4, %cl # moves left by four since bit we want to check is in fourth position # tests to see if desired bit is one testb %cl, BATT_STATUS_PORT(%rip) # tests to see if the fourth bit is one jz line_41_else # jumps if the fourth bit is not one, percent mode, sets mode to two movb $1, 3(%rdi) # if the bit is one (volt) mode is set to 1 movq $0x00, %rax # returns 0, sucsess ret # set_bat_from_ports helpers return_one: # base case returns one movq $0, %rax # clears register movl $1, %eax # sets that register to one ret # returns one line_37_check: # sets percent to zero when volts are too low movb $0, 2(%rdi) # rdi (batt) percent field set to 0 jmp jmp_back_37 # jump to continue initializing batt line_38_check: # sets percent to 100 if volts too high movb $100, 2(%rdi) # rdi (batt) percent field capped to 100 jmp jmp_back_38 # jumps back to continue intializing batt line_41_else: # sets mode to two and returns zero movb $2, 3(%rdi) # sets rdi (batt) mode field to be 2 for percent movq $0x00, %rax # returns 0 since sucsess, end of method ret # ## Change to definint semi-global variables used with the next function # ## via the '.data' directive # You can make your own data and then use it in function .data my_int: # declare location an single integer named 'my_int' .int 1234 # value 1234 other_int: # declare another int accessible via name 'other_int' .int 0b0101 # binary value as per C my_array: # declare multiple ints sequentially starting at location .int 10 # 'my_array' for an array. Each are spaced 4 bytes from the .int 0x00014 # next and can be given values using the same prefixes as .int 0b11110 # used for set_display_from_batt:, accsess to get number bit patterns for display mask_array: .int 0b0111111 .int 0b0000110 .int 0b1011011 .int 0b1001111 .int 0b1100110 .int 0b1101101 .int 0b1111101 .int 0b0000111 .int 0b1111111 .int 0b1101111 # # WARNING: Don't forget to switch back to .text as below # # Otherwise you may get weird permission errors when executing .text .global set_display_from_batt ## ENTRY POINT FOR REQUIRED FUNCTION set_display_from_batt: # set up and determining mode movl $0, (%rsi) # sets display to zero for start, line 73 movq $0, %rax # clears register movq $0, %rcx # clears register movq $0, %rdx # clears register movl %edi, %ecx # gets batt puts into ecx to extract mode sarl $24, %ecx # shifts to the mode # determines mode cmpl $2, %ecx # compares the mode to 2 jne mode_1_percent # if mode is not 2, it must be 1 so jump to percent # start of volts calculation when mode is 2 movq $0, %r12 # clears register movl $0b110, %r12d # bit pattern for deciman and display 'v' orl %r12d, (%rsi) # adds the bit pattern to the display # rcx = batt_mvolts movw %di, %cx # moves mvolts (2bytes) into cx # gets rid of last digit and check if rounding is needed movq $0, %rax # clears rax register movw %cx, %ax # puts mvolts into rax movq $0, %r12 # clears register movw $10, %r12w # moves ten in to be denomenator idivw %r12w # divides mvolts by ten movw %ax, %cx # moves remainder into cx cmpw $5, %dx # check for rounding jge add_one # if you need to add one jump to do so round_return: # after rounding jump back for volts calculation # or if no rounding, continue for volts calculation # division division division to calculate volts # VVVV REGISTER KEY VVVVVVV # ecx is mvolts # eax gets rid of last digit when set back to rcx # rdx has the modulo number to set value # r12 holds the number 10 # r13 hold pointer to mask array # r14 holds the binary that is being transfered to the display # setting up calculation movq $0, %r14 # clear register movq $0, %r13 # clear register # set up continue leaq mask_array(%rip),%r13 # gets the array of the bit patterns for numbers movw %cx, %ax # puts the volts (without last digit) in ax register for division movw $10, %r12w # puts 10 into r12 register to be denominator # calculating digit 1 movq $0, %rdx # initialize remainder variable idivw %r12w # divide/modulo volts by 10 movl (%r13, %rdx, 4), %r14d # gets the bit pattern based on remainder sall $3, %r14d # shift to get into position to or orl %r14d, (%rsi) # adds new number bit pattern to display # calculate digit 2 movw $10, %r12w # puts 10 into r12 register to be denominator movq $0, %rdx # initialize remainder variable idivw %r12w # divide/modulo leftover of volts by 10 movl (%r13,%rdx,4), %r14d # gets the bit pattern based on remainder sall $10, %r14d # shift to get into position to or orl %r14d, (%rsi) # adds new number bit pattern to display # calculate digit 3 movw $10, %r12w # puts 10 into r12 register to be denominator movq $0, %rdx # initialize remainder variable idivw %r12w # divide/modulo leftover of volts by 10 movl (%r13,%rdx,4), %r14d # gets the bit pattern based on remainder sall $17, %r14d # shift to get into position to or orl %r14d, (%rsi) # adds new number bit pattern to display percent_return: # both the percent version and volts version needs a battery update # so if percent, jumps back here, or continues on if volts # battery manager, getting percent movq $0, %r15 # clears register used to hold battery percent movl %edi, %r15d # moves batt to be turned into battery percent sarl $16, %r15d # r15b now has battpercent in it # comparing percent to know how many bars to add cmpb $90, %r15b # if above 90, jumps to set correct bit pattern jge percent90 cmpb $70, %r15b # if above 70, jumps to set correct bit pattern jge percent70 cmpb $50, %r15b # if above 50, jumps to set correct bit pattern jge percent50 cmpb $30, %r15b # if above 30, jumps to set correct bit pattern jge percent30 cmpb $5, %r15b # if above 5, jumps to set correct bit pattern jge percent5 # if no bars of battery V end method return 0, sucsses return_0: # returns 0 movq $0, %rax ret percent5: # if battery is at one bar movq $0, %r12 # clear register movl $0b00001, %r12d # moves one bar bit pattern into register sall $24, %r12d # shifts it to correct position orl %r12d, (%rsi) # adds to display jmp return_0 # end method, sucsses percent30: movq $0, %r12 # clear register movl $0b00011, %r12d # moves two bar bit pattern into register sall $24, %r12d # shifts it to correct position orl %r12d, (%rsi) # adds to display jmp return_0 # end method, sucsses percent50: movq $0, %r12 # clear register movl $0b00111, %r12d # moves three bar bit pattern into register sall $24, %r12d # shifts it to correct position orl %r12d, (%rsi) # adds to display jmp return_0 # end method, sucsses percent70: movq $0, %r12 # clear register movl $0b01111, %r12d # moves four bar bit pattern into register sall $24, %r12d # shifts it to correct position orl %r12d, (%rsi) # adds to display jmp return_0 # end method, succsses percent90: movq $0, %r12 # clear register movl $0b11111, %r12d # moves five bar bit pattern into register sall $24, %r12d # shifts it to correct position orl %r12d, (%rsi) # adds to display jmp return_0 # end method, sucsses mode_1_percent: # division division division to caulate the percent # VVVV REGISTER KEY VVVVVVVV # ecx is mvolts # eax gets rid of last digit when set back to rcx # rdx has the modulo number to set value # r12 holds the number 10 # r13 hold pointer to mask array # r14 holds the binary that is being transfered to the display # setting 'p' and no decimal movq $0, %r12 # clear register movl $0b001, %r12d # bit pattern for percent sign and no decimal orl %r12d, (%rsi) # adds the bit pattern to display # set up for calulation movl %edi, %ecx # moves batt into ecx to extract percent sarl $16, %ecx # moves to percent bits movq $0, %r14 # clears register movq $0, %r13 # clears register leaq mask_array(%rip),%r13 # get the bit array with number masks # calculation begins, digit one movq $0, %rax # clear register movb %cl, %al # moves percent into %rax movq $0, %r12 # clear register movb $10, %r12b # moves ten into register to be denominator movq $0, %rdx # clear remainder register idivq %r12 # divide/modulo by 10 movl (%r13, %rdx, 4), %r14d # gets mask based on remainder and stores in register r14 sall $3, %r14d # moves the bit mask into position orl %r14d, (%rsi) # adds it to display cmpb $0, %al # checks if we are at the last digit je percent_return # if so returns to add battery bits # calculate digit two movb $10, %r12b # moves ten into register to be denominator movq $0, %rdx # clear remainder register idivq %r12 # divide/modulo by 10 movl (%r13, %rdx, 4), %r14d # gets corresponding bit mask from remainder sall $10, %r14d # shifts bit mask into position orl %r14d, (%rsi) # adds bits to display cmpb $0, %al # checks if we are at the last digit je percent_return # if so returns to add battery bits # calculates third digit movq $0, %rdx # clear remainder register idivq %r12 # divide/modulo by 10 movl (%r13, %rdx, 4), %r14d # get bit mask corresponding to remainder sall $17, %r14d # shifts bit mask into position orl %r14d, (%rsi) # adds bit mask to display jmp percent_return # no more possible digits, jumps to calculate battery digits add_one: # uesed when rounding for mvolts addl $1, %ecx # adds one to ecx, which holds volt number jmp round_return # returns back to continue volt calculation # # ENTRY POINT FOR REQUIRED FUNCTION .text .global batt_update batt_update: # # assembly instructions here pushq $0 # create space for batt and aligns for call movq %rsp, %rdi # moves address of port into rdi call set_batt_from_ports # calls set batt from ports with rdi as input rax as output cmpq $1, %rax # error check je return_one_update # is fails returns one leaq 4(%rsp), %rsi # gets the adress for the diaply movl (%rdi), %edi # moves the value of the batt into edi call set_display_from_batt movq (%rsi), %rsi # gets the value of rsi back into rsi movl %esi, BATT_DISPLAY_PORT(%rip) # puts the display into the global display value popq %rsi # free space from pushing # returns 0 for sucsess movq $0, %rax ret return_one_update: # i f fails popq %rsi # bring back stack from push movq $1, %rax # returns one for failure ret