The function inventory take an array of device pointers and call evaluate to find out what the variation is. The inventory function then returns a pointer that has the highest variation.
unsigned short evaluate(Struct Device *thing); struct Device *inventory(struct Device *things[], int count); device.h:
struct Device{ char name[20]; short adjustments[8]; short avg; } main.c:
#include <stdio.h> #include <stdlib.h> #include "device.h" /* from device.h, shown here to make it easier to code struct Device { char name[20]; short adjustments[8]; short avg; }; */ struct Device things[] = { { "Museum Quality",{ 0, 1, 0, -1, 0, -1, 0, 1}, 1 }, { "Fell off truck", { 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff}, 2 }, /* the casts are there since C constants are ints and you can't make * them shorts and negative numbers look like overflow */ { "Fell down stairs", { 0x7ff0, (unsigned short)0x800f, 0x7ffe, (unsigned short)0x8001, 0x7ffd, (unsigned short)0x8002, 0x7fff, 0x7f00}, 3 }, { "On left side",{ 10, 11, 10, 12, 10, 13, 10, 14}, 4 }, { "On right side",{ -300, -321, -320, -332, -320, -313, -310, -314}, 5 } }; /* struct Device *inventory(struct Device *things[], int count); */ int main() { struct Device *pointers[1 + sizeof(things) / sizeof(things[0])] = {NULL}; const int count = sizeof(things) / sizeof(things[0]); struct Device *worst = NULL; int i; for (i=0; i< count; i++) { printf("Loading %s into pointers\n", things[i].name); pointers[i] = &things[i]; } pointers[i] = NULL; worst = inventory(pointers, count); printf("main: The worst is %s\n", worst->name); return(EXIT_SUCCESS); } calibrate.s:
.file "calibrate.s" #optional directive .section .rodata #required directives for rodata .data #required for file scope data: read-write program data #of static storage class .globl calibrate #required directive for every function .type calibrate, @function #required directive .text #required directive - code begins here calibrate: pushq %rbp #stack housekeeping #1 movq %rsp, %rbp #stack housekeeping #2 movq $0, %r10 #initialize counter to 0 movq $0, %r11 #initialize sum to be 0 movswq 20(%rdi),%rcx #initialize min to first element movswq 20(%rdi),%rdx #initialize max to first element loop: movswq 20(%rdi,%r10,2), %rax #copy first parameter into rax cmpq %rdx, %rax jle skipmax movq %rax, %rdx skipmax: cmpq %rcx, %rax jge skipmin movq %rax, %rcx skipmin: addq %rax, %r11 incq %r10 cmpq $8,%r10 je exit jmp loop exit: movq %r11, %rax sarq $3, %rax movl %eax, 36(%rdi) subq %rcx, %rdx movq %rdx, %rax leave #return stack to original values ret #return .size calibrate, .-calibrate #required directive evaluate.s:
.file "evaluate.s" #optional directive .section .rodata #required directives for rodata .LC0: .string "\nevaluate: %s currently has an adjustment of %i\n" .LC1: .string "evaluate: new adjustment is %i, variability is %i\n" .data #required for file scope data: read-write program data #of static storage class .globl evaluate #required directive for every function .type evaluate, @function #required directive .text #required directive - code begins here evaluate: pushq %rbp #stack housekeeping #1 movq %rsp, %rbp #stack housekeeping #2 pushq %r12 pushq %r13 pushq %r14 movq %rdi, %r14 #r14 stores the device struct movq 36(%r14), %r13 #r13 stores the old avg call calibrate movq %rax, %r12 #r12 stores variability movq %r13, %rdx movq %r14, %rsi #copy the name to the second parameter movq $.LC0, %rdi movq $0, %rax call printf movq %r12, %rdx movq 36(%r14), %rsi #copy new average to second parameter movq $.LC1, %rdi movq $0, %rax call printf movq %r12, %rax popq %r14 popq %r13 popq %r12 leave #return stack to original values ret #return .size evaluate, .-evaluate #required directive inventory.s:
rdi is the parameter that holds an array of device pointers, #rbx is a copy of rdi, so it stores array of pointers of devices, #r12 stores count of valid pointers, #r14 stores max variation, #r15 stores the device pointer with the most variation.
.file "inventory.s" #optional directive .section .rodata #required directives for rodata .LC0: .string "\ninventory: The minimum variation is %i\n" .LC1: .string "inventory: The maximum variation is %i from %s\n" .data #required for file scope data: read-write program data #of static storage class .globl inventory #required directive for every function .type inventory, @function #required directive .text #required directive - code begins here inventory: pushq %rbp #stack housekeeping #1 movq %rsp, %rbp #stack housekeeping #2 pushq %rbx pushq %r12 pushq %r13 pushq %r14 pushq %r15 movq %rdi, %rbx #rbx stores array pointer things decq %rsi movq %rsi, %r12 #r12 stores count of valid pointers movq $32767, %r13 #r13 stores min variability movq $0, %r14 #r14 store max variability movq %rdi, %r15 #r15 stores pointer with most variable loop: movq (%rbx,%r12,8), %rdi call evaluate cmpq %r14, %rax jle skipmax movq %rax, %r14 movq (%rbx, %r12,8), %r15 skipmax: cmpq %r13, %rax jge skipmin movq %rax, %r13 skipmin: decq %r12 cmpq $0, %r12 jge loop movq %r13, %rsi movq $.LC0, %rdi movq $0, %rax call printf movq %r15, %rdx movq %r14, %rsi movq $.LC1, %rdi movq $0, %rax call printf movq %r15, %rax popq %r15 popq %r14 popq %r13 popq %r12 popq %rbx leave #return stack to original values ret #return .size inventory, .-inventory #required directive I run the program, result is: r14 is getting the highest variation correctly, but LC0 prints correct highest variability (r14) but empty name (r15), and the C program that is trying to print the name stored in rax is also empty, the print statement prints:
The maximum variation is 65534 from
instead, it should print:
The maximum variation is 65534 from Mount Everst
The name is not being printed as you can see from above.
The main c program that calls inventory looks like this:
struct Device *worst = inventory(pointers, count); printf("The worst is %s\n", worst->name); So, the output from the main program prints as following: The worst is
in other words, worst->name is not being printed at all.
after Further trouble shooting, I found out that r15 has the correct pointer, and its adjustment and avg values are correct, it is just name is empty string, any idea why? maybe since the name is a char array, and it is not being copied correctly?
Thanks!
https://stackoverflow.com/questions/67014883/assembly-how-to-return-a-pointer April 09, 2021 at 11:57AM
没有评论:
发表评论