Question: here my c code-#include batt.h //int set_batt_from_ports(batt_t *batt); // Uses the two global variables (ports) BATT_VOLTAGE_PORT and // BATT_STATUS_PORT to set the fields of the
here my c code-#include "batt.h"
//int set_batt_from_ports(batt_t *batt);
// Uses the two global variables (ports) BATT_VOLTAGE_PORT and
// BATT_STATUS_PORT to set the fields of the parameter 'batt'. If
// BATT_VOLTAGE_PORT is negative, then battery has been wired wrong;
// no fields of 'batt' are changed and 1 is returned to indicate an
// error. Otherwise, sets fields of batt based on reading the voltage
// value and converting to percent using the provided formula. Returns
// 0 on a successful execution with no errors. This function DOES NOT
// modify any global variables but may access global variables.
//
// CONSTRAINT: Avoids the use of the division operation as much as
// possible. Makes use of shift operations in place of division where
// possible.
//
// CONSTRAINT: Uses only integer operations. No floating point
// operations are used as the target machine does not have a FPU.
int set_batt_from_ports(batt_t *batt) {
if (BATT_VOLTAGE_PORT
return 1;
}
// voltage conversion
batt->mlvolts = BATT_VOLTAGE_PORT / 2;
// percent based on voltage range
if (batt->mlvolts
batt->percent = 0;
} else if (batt->mlvolts > 3800) {
batt->percent = 100;
} else {
batt->percent = (batt->mlvolts - 3000) / 8;
}
// clamp within range
if (batt->percent > 100) {
batt->percent = 100;
}
// determine mode bit
if (BATT_STATUS_PORT & (1
batt->mode = 1;
} else {
batt->mode = 2;
}
return 0;
}
//int set_display_from_batt(batt_t batt, int *display);
// Alters the bits of integer pointed to by 'display' to reflect the
// data in struct param 'batt'. Does not assume any specific bit
// pattern stored at 'display' and completely resets all bits in it on
// successfully completing. Selects either to show Percent (mode=1) or
// Volts (mode=2). If Volts are displayed, only displays 3 digits
// rounding the lowest digit up or down appropriate to the last digit.
// Calculates each digit to display changes bits at 'display' to show
// the volts/percent according to the pattern for each digit. Modifies
// additional bits to show a decimal place for volts and a 'V' or '%'
// indicator appropriate to the mode. In both modes, places bars in
// the level display as indicated by percentage cutoffs in provided
// diagrams. This function DOES NOT modify any global variables but
// may access global variables.
//
// ERRORS: Early in the function checks that the `mlvolts` field is
// positive and the `mode` field is either 1 or 2. If not, immediately
// returns 1 without changing the `display` parameter. (This error
// checking is new and was not presnet in the Project 2 version)
int set_display_from_batt(batt_t batt, int *display) {
// Set the display bits based on battery data.
int display_bits[11] = {
0b0111111, 0b0000110, 0b1011011, 0b1001111, 0b1100110,
0b1101101, 0b1111101, 0b0000111, 0b1111111, 0b1101111, 0
};
// Shows volts and percent .
int mv;
if (batt.mlvolts
mv = 0;
else
mv = batt.mlvolts;
if (batt.percent
batt.percent = 0;
int left_digit = 10, middle_digit = 10, right_digit = 10;
unsigned int disp = 0;
// volts mode
if (batt.mode == 2 && mv == 0 && batt.percent == 0) {
left_digit = 0; middle_digit = 0; right_digit = 0;
disp |= (1
} else if (batt.mode == 2) {
int r = (mv + 5) / 10;
left_digit = mv / 1000;
middle_digit = (mv / 100) % 10;
right_digit = r % 10;
disp |= (1
//percent mode
} else {
if (batt.percent > 100)
batt.percent = 100;
if (batt.percent == 100) {
left_digit = 1; middle_digit = 0; right_digit = 0;
} else if (batt.percent >= 10) {
middle_digit = batt.percent / 10;
right_digit = batt.percent % 10;
} else {
right_digit = batt.percent;
}
disp |= (1
}
// add level bars
disp |= (batt.percent > 89)
disp |= (batt.percent > 69)
disp |= (batt.percent > 49)
disp |= (batt.percent > 29)
disp |= (batt.percent > 4)
// add digits
disp |= (display_bits[left_digit]
disp |= (display_bits[middle_digit]
disp |= (display_bits[right_digit]
// pointed integer
*display = disp;
return 0;
}
//int batt_update();
// Called to update the battery meter display. Makes use of
// set_batt_from_ports() and set_display_from_batt() to access battery
// voltage sensor then set the display. Checks these functions and if
// they indicate an error, does NOT change the display. If functions
// succeed, modifies BATT_DISPLAY_PORT to show current battery level.
//
// CONSTRAINT: Does not allocate any heap memory as malloc() is NOT
// available on the target microcontroller. Uses stack and global
// memory only.
int batt_update() {
// local battery data
batt_t batt;
int result = set_batt_from_ports(&batt);
// read battery data from ports
if (result != 0) // check error
return 1;
// holds display bits
int display;
set_display_from_batt(batt, &display);
// output the new display to the hardware port
BATT_DISPLAY_PORT = display;
return 0;
}
and my assabmly verson-text .global set_batt_from_ports
## ENTRY POINT FOR REQUIRED FUNCTION set_batt_from_ports: movw BATT_VOLTAGE_PORT(%rip), %ax # # Loads 16-bit voltage reading into AX register cmp $0x0, %ax jl .FAIL_SET # fails if BATT_VOLTAGE_PORT is negative sarw $0x1, %ax # div by 2 movw %ax, (%rdi) # set mvolts field of batt struc cmp $0x0bb8, %ax # checks if the percentage is less than 0 jl .MIN_PERCENT cmp $0x0ed8, %ax # checks if the percentage is greater than 100 jg .MAX_PERCENT subw $0x0bb8, %ax sarw $0x3, %ax movb %al, 0x2(%rdi) # puts mvolts -3000 / 8 into percent field of batt struct jmp .AFTER_PERCENT
.MIN_PERCENT: movb $0x00, 0x2(%rdi) # puts 0 into percent field of batt struct jmp .AFTER_PERCENT .MAX_PERCENT: movb $0x64, 0x2(%rdi) # puts 100 into percent field of batt struct .AFTER_PERCENT: movb BATT_STATUS_PORT(%rip), %al andb $0x10, %al # masks all but bit 3 of BATT_STATUS_PORT cmpb $0x00, %al je .MODE_TWO movb $0x01, 0x3(%rdi) # puts mode into mode field of batt struct jmp .DONE_MODE .MODE_TWO: movb $0x02, 0x3(%rdi) .DONE_MODE: xor %eax, %eax ret .FAIL_SET: movl $0x1, %eax # returns a value of 1 ret
### Change to definint semi-global variables used with the next function ### via the '.data' directive .data
seven_segment_encoder: # Encodes decimal 0..9 and blank (10) .int 0b0111111 # 0 .int 0b0000110 # 1 .int 0b1011011 # 2 .int 0b1001111 # 3 .int 0b1100110 # 4 .int 0b1101101 # 5 .int 0b1111101 # 6 .int 0b0000111 # 7 .int 0b1111111 # 8 .int 0b1101111 # 9 .int 0b0000000 # blank (10)
## 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 ### int set_display_from_batt(batt_t batt, int *display) set_display_from_batt: push %rbx # save registers push %r12 push %r13 push %r14 push %r15 subq $8, %rsp # stack alignment xor %r10d, %r10d # clear display bits ## Extract mode (top byte) movl %edi, %r8d # copy batt andl $0xff000000, %r8d # mask top byte sarl $24, %r8d # shift down to mode (1=%, 2=V)
## Validate mode cmp $2, %r8d # compare to 2 je .MODE_OK # jump if 2 cmp $1, %r8d # compare to 1 je .MODE_OK # jump if 1 movl $1, %eax # return 1 (invalid) jmp .RETURN ## Check mlvolts > 0 .MODE_OK: movl %edi, %eax # copy batt shll $16, %eax # move mlvolts to top sarl $16, %eax # sign extend test %eax, %eax # test if > 0 jge .MLV_OK # ok if >= 0 movl $1, %eax # invalid jmp .RETURN ## Extract percent (bits 16-23) .MLV_OK: movl %edi, %r9d # copy batt andl $0x00ff0000, %r9d # mask percent sarl $16, %r9d # shift down to get percent ## Level bars (bits 24-28) movl %r9d, %eax # load percent cmpl $4, %eax # check >4 jle .NO_BAR0 movl $1, %ecx sall $24, %ecx # bit 24 orl %ecx, %r10d .NO_BAR0: movl %r9d, %eax cmpl $29, %eax # check >29 jle .NO_BAR1 movl $1, %ecx sall $25, %ecx # bit 25 orl %ecx, %r10d .NO_BAR1: movl %r9d, %eax cmpl $49, %eax # check >49 jle .NO_BAR2 movl $1, %ecx sall $26, %ecx # bit 26 orl %ecx, %r10d .NO_BAR2: movl %r9d, %eax cmpl $69, %eax # check >69 jle .NO_BAR3 movl $1, %ecx sall $27, %ecx # bit 27 orl %ecx, %r10d .NO_BAR3: movl %r9d, %eax cmpl $89, %eax # check >89 jle .NO_BAR4 movl $1, %ecx sall $28, %ecx # bit 28 orl %ecx, %r10d
## Mode indicator bits .NO_BAR4: cmp $2, %r8d # volts mode? jne .PERCENT_BITS movl $1, %eax sall $1, %eax # bit 1 orl %eax, %r10d sall $1, %eax # bit 2 orl %eax, %r10d jmp .AFTER_MODE_BITS .PERCENT_BITS: movl $1, %eax # bit 0 for percent orl %eax, %r10d .AFTER_MODE_BITS: cmp $2, %r8d # mode check again je .SHOW_VOLTS jmp .SHOW_PERCENT ## Voltage Mode (V) .SHOW_VOLTS: movl %edi, %r11d andl $0x0000ffff, %r11d # isolate mlvolts
movl %r11d, %eax xorl %edx, %edx movl $1000, %ecx divl %ecx movl %eax, %r12d # left digit = mv/1000
movl %r11d, %eax xorl %edx, %edx movl $100, %ecx divl %ecx xorl %edx, %edx movl $10, %ecx divl %ecx movl %edx, %r15d # middle = (mv/100)%10
movl %r11d, %eax addl $5, %eax # round xorl %edx, %edx movl $10, %ecx divl %ecx xorl %edx, %edx movl $10, %ecx divl %ecx movl %edx, %r9d # right = ((mv+5)/10)%10 leaq seven_segment_encoder(%rip), %rbx movl (%rbx,%r9,4), %eax sall $3, %eax orl %eax, %r10d movl (%rbx,%r15,4), %eax sall $10, %eax orl %eax, %r10d movl (%rbx,%r12,4), %eax sall $17, %eax orl %eax, %r10d jmp .END_NUMBERS ## Percent Mode (%) .SHOW_PERCENT: movl %edi, %r11d andl $0x00ff0000, %r11d sarl $16, %r11d # get percent
movl %r11d, %eax xorl %edx, %edx movl $100, %ecx divl %ecx movl %eax, %r12d # left = percent/100 movl $0, %r8d test %eax, %eax jne .LEFT_OK movl $10, %r12d # blank if zero movl $1, %r8d .LEFT_OK: movl %r11d, %eax xorl %edx, %edx movl $10, %ecx divl %ecx movl %edx, %r14d # right = % % 10 movl %eax, %eax xorl %edx, %edx movl $10, %ecx divl %ecx movl %edx, %r13d # middle = (%/10)%10
cmp $1, %r8d jne .MIDDLE_OK test %r13d, %r13d jne .MIDDLE_OK movl $10, %r13d # blank middle if left blank .MIDDLE_OK: leaq seven_segment_encoder(%rip), %rbx movl (%rbx,%r14,4), %eax sall $3, %eax orl %eax, %r10d movl (%rbx,%r13,4), %eax sall $10, %eax orl %eax, %r10d movl (%rbx,%r12,4), %eax sall $17, %eax orl %eax, %r10d ### Write result and return .END_NUMBERS: movl %r10d, (%rsi) # *display = disp xorl %eax, %eax # return 0 jmp .RETURN
.RETURN: addq $8, %rsp # restore stack pop %r15 pop %r14 pop %r13 pop %r12 pop %rbx ret # return
.text .global batt_update
## ENTRY POINT FOR REQUIRED FUNCTION batt_update: subq $0x10, %rsp leaq (%rsp), %rdi # rdi = &batt call set_batt_from_ports # returns result in eax cmp $0x0, %eax jne .FAIL # if nonzero, jump to fail movl 0(%rsp), %edi # load batt.mlvolts (2 bytes) into edi movzbl 2(%rsp), %esi # load batt.percent as byte ??? zero-extend to 32 bits shll $16, %esi # move into bits [23:16] orl %esi, %edi # combine with mlvolts movzbl 3(%rsp), %esi # load batt.mode byte shll $24, %esi # move into bits [31:24] orl %esi, %edi # combine all into edi leaq 8(%rsp), %rsi # rsi = &display call set_display_from_batt movl 8(%rsp), %eax # load display value movl %eax, BATT_DISPLAY_PORT(%rip) xor %eax, %eax # eax = 0 (return value) addq $0x10, %rsp # restore stack ret .FAIL: movl $1, %eax # return 1 addq $0x10, %rsp # restore stack ret
rewrite the assamly code with easy and simple verson
Step by Step Solution
There are 3 Steps involved in it
Get step-by-step solutions from verified subject matter experts
