computing-systems-212 / Lab 1 (P2): OO ARM Disassembly / task3 / ANSWERS.txt
ANSWERS.txt
Raw
Q1. From the perspective of the object hierarchy, what happens to the first parameter passed to task3?

./task3 *param1* param2 
The first parameter acts as some sort of name argument.

Parameters passed to task3 are stored on the stack as such:
  (gdb) x/4xg 0xfffffffff460 (original sp)
  0xfffffffff460: 0x0000000000000003 (number of parameters)   0x0000fffffffff6c0 (./task3 parameter)
  0xfffffffff470: 0x0000fffffffff6e6 (1st arg)                0x0000fffffffff6ed (2nd arg)
The following code snippet indicates that the first parameter's address is loaded into x25 from the stack, byte-shifted 2 bytes above the original sp.

  400164:	f94003f8 	ldr	x24, [sp]                      // _start: load number of args provided (stored in stack)
  *******
  40017c:	f9400ff8 	ldr	x24, [sp, #24]                 // load from stack shifted 3 bytes (sp -> ./task3 --> 1st arg --> 2nd arg)
  400180:	94000020 	bl	0x400200                       // branch with link to 0x400200
  400184:	d10083ff 	sub	sp, sp, #0x20                  // allocate space on stack 4 bytes (32 bits (0x20)) on stack
  400188:	910003f8 	mov	x24, sp                        // move new stack pointer onto x24
  40018c:	f9401bf9 	ldr	x25, [sp, #48]                 // load x25 with stack pointer shifted 6 bytes (sp -> new alloc -> ... -> 1st arg)

The address value loaded is:
  (gdb) p/x $x25
  $1 = 0xfffffffff6e6

The register holding this value is later stored in a virtual table here:
  4000fc:	f900031a 	str	x26, [x24]               //x24          // store 2nd arg from x26 into address stored in x24
  400100:	91002318 	add	x24, x24, #0x8                          // add 8(0x8) to address value stored in reg x24
  400104:	94000014 	bl	0x400154                                // branch with link to 0x400154 - JUMP8
  *******
  400154:	f9000319 	str	x25, [x24]              //x24+1         // JUMP8: store 1st arg from x25 into address stored in x24 (1 byte above 2nd arg)
It becomes a member of the instance of the class Person, inheriting from the  class Named stored in the field name.
Ultimately (and conditionally on the age field!), it is used in the method print_name to write back to the user.
----------------------------------------------------------------------------------

Q2. From the perspective of the object hierarchy, what happens to the second parameter passed to task3?

./task3 param1 *param2*
The second argument acts as some sort of age argument and influences the output written back to the user.

Referencing the code snippet from Q1, the second parameter's address is loaded into x24 from the stack, byte-shifted 3 bytes above the original sp.
  40017c:	f9400ff8 	ldr	x24, [sp, #24]                 // load from stack shifted 3 bytes (sp -> ./task3 --> 1st arg --> 2nd arg)

The value loaded is:
(gdb) p/x $x24
$1 = 0xfffffffff6ed

The register holding this value is later stored in the same virtual table here:
  4000fc:	f900031a 	str	x26, [x24]               //x24          // store 2nd arg from x26 into address stored in x24
  400100:	91002318 	add	x24, x24, #0x8                          // add 8(0x8) to address value stored in reg x24
It becomes a member of the instance of the class Person, stored in the field age, and used to loop through a method get_age "check".
----------------------------------------------------------------------------------

Q3. How does the program behaviour change depending on the value of the second parameter? You must provided the exact ranges of the second parameter for each behaviour.

Since the second argument is an "age" argument, it requires the user to provide input of a specific type.
The second parameter must contain only (hex) characters 0(0x30) or above:
  400210:	7100c339 	subs	w25, w25, #0x30                       // subtract 48(0x30) from register byte
  400214:	540000a4 	b.mi	0x400228  // b.first                  // branch if w25 negative(char below 0) - JUMP4 (CONDITION NOT MET)
The second parameter must contain only (hex) characters 9(0x39) or below:
  400218:	71002b3f 	cmp	w25, #0xa                               // compare by doing w25 subtract 10(0xa)
  40021c:	54000065 	b.pl	0x400228  // b.nfrst                  // branch if above diff is positive(char above 9) - JUMP5 (CONDITION NOT MET)
The second paramter later gets checked to be greater than 1(0x1) overall:
  400128:	f10007bf 	cmp	x29, #0x1                               // compare 2nd arg with 1 (x29 - 1)
  40012c:	54000088 	b.hi	0x40013c  // b.pmore                  // branch to 0x40013c if unsigned higher - JUMP11 (CONDITION MET)

If these conditions are not met, the program will resort to outputting the text "goo goo" to the user.
Ultimately, the second argument must contain digits from 0-9 and must be greater than 1 in order for the program to output the provided name string.
----------------------------------------------------------------------------------

Q4. List all of the **object methods** implemented in the task3 binary, including constructor. For each method, provide the class name and the method name (or "constructor"), and the address at which the method resides in memory.

class Named:
    constructor: 0x4000f8
    method print_name: 0x4000b0

class Person:
    constructor: 0x400154
    method get_age: 0x400200

(fields are not methods)
----------------------------------------------------------------------------------

Q5. List each virtual table defined in the binary, and explain the layout: that is, if the virtual table is at address A, what value is at A, what value is at A+8, and so on.

The named virtual table is at address A (0x4001c0).
  400158:	10000359 	adr	x25, 0x4001c0
A+8: The 1st user arg provided by user.
  400154:	f9000319 	str	x25, [x24]     //named  //x24+1         // JUMP8: store 1st arg from x25 into address stored in x24 (1 byte above 2nd arg)

The person virtual table is at address B (0x4001f0).
  40010c:	10000739 	adr	x25, 0x4001f0
A+8: The 1st user arg provided by user casted from the Named superclass.
  400154:	f9000319 	str	x25, [x24]     //named  //x24+1         // JUMP8: store 1st arg from x25 into address stored in x24 (1 byte above 2nd arg)
A+16: The 2nd user arg provided by user.
  4000fc:	f900031a 	str	x26, [x24]               //x24          // store 2nd arg from x26 into address stored in x24
----------------------------------------------------------------------------------

Q6. List the object layout for every object class defined in the binary: that is, if the object table is at address A, what value is at A, what value is at A+8, and so on.

Since the object is allocated onto the stack, this will be A
Person Class Object: 
    inherited field name 0xfffffffff470 -> A+16
    inherited method print_name 0xfffffffff480 -> A+32
    field age 0xfffffffff478 -> A+24
    method get_age 0xfffffffff488 A+40
The fields provided by the args were allocated above the stack after the ./task3 arg.
This was then followed by the allocation of the methods stored on the stack further above.
----------------------------------------------------------------------------------

Q7. Explain how the Person subclass is cast to the Named superclass. Include the relevant sequence of instructions and the address at which it occurs in the binary.

The Person subclass at 0x4000f8 goes through constructor steps and then stores the user 2nd arg into the bottom of the virtual table.
After a byte-shift, a branch with link occurs to 0x400154, casting into the Named superclass, storing the 1st arg name in the virtual table.
The virtual table address is also stored (and overwritten due to virtual method).
  4000f8:	a9bf63fe 	stp	x30, x24, [sp, #-16]!    //person       // store new sp(x24) and lr(x30) 2 bytes below stack pointer
  4000fc:	f900031a 	str	x26, [x24]               //x24          // store 2nd arg from x26 into address stored in x24
  400100:	91002318 	add	x24, x24, #0x8                          // add 8(0x8) to address value stored in reg x24
  400104:	94000014 	bl	0x400154                                // branch with link to 0x400154 - JUMP8
  *******
  400154:	f9000319 	str	x25, [x24]     //named  //x24+1         // JUMP8: store 1st arg from x25 into address stored in x24 (1 byte above 2nd arg)
  400158:	10000359 	adr	x25, 0x4001c0                           // store pc-relative address of 0x4001c0 in x25
  40015c:	f9000719 	str	x25, [x24, #8]          //x24+2         // store pc-relative address into address stored in shifted x24 (1 byte above 1st arg)
  400160:	d65f03c0 	ret                                         // return to caller of JUMP8
----------------------------------------------------------------------------------

Q8. Which, if any, methods are overridden in the subclass? For each method, explain the implementation in terms of pseudocode / object concepts. Parroting the assembly code here will receive no credit.

In the subclass, the below method is overwritten.
The virtual name method extended from Named is overwritten in the subclass Person, as the virtual method ensures that the object type is only known at runtime.
This is part of the process that takes the user-provided name and outputs it within the "I am ___!" string back to the user.
  400158:	10000359 	adr	x25, 0x4001c0                           // store pc-relative address of 0x4001c0 in x25
  40015c:	f9000719 	str	x25, [x24, #8]          //x24+2         // store pc-relative address into address stored in shifted x24 (1 byte above 1st arg)
  400160:	d65f03c0 	ret                                         // return to caller of JUMP8
  *******
  40010c:	10000739 	adr	x25, 0x4001f0                           // store pc-relative address of 0x4001f0 in x25
  400110:	f9000b19 	str	x25, [x24, #16]          //x24+2        // store pc-relative address into 2 byte shifted reg x24 (overwrites 0x4001c0)
  400114:	d65f03c0 	ret                                         // return to caller of JUMP7
----------------------------------------------------------------------------------

Q9. List all instances where an object calls its own methods via the virtual table. Include the *address of each method* in which this occurs, and a pseudocode explanation of what is going on (again, not assembly).

In the case of the Person class, it calls the print_name through the extended Named class by going through the virtual table.
The virtual table is used for when the runtime needs to know which method to call,
which is important in this case for the program to write the name argument back to the user.
  4001e0:	97ffffb4 	bl	0x4000b0                                // branch with link to 0x4000b0 - JUMP16 (print arg 1)

Q10. List all instances where an object calls its own methods via the virtual table. Include the *address of each method* in which this occurs, and a pseudocode explanation of what is going on (again, not assembly).
See above question.
----------------------------------------------------------------------------------

Q11. List all instances where an object calls its own methods without going through the virtual table. Include the *address of each method* in which this occurs, and a pseudocode explanation of what is going on (again, not assembly). Why does this happen?

In the case of the Person class, it calls its own get_age method without going through the virtual table.
Since the get_age method is local to the Person class and is not inheriting anything from the Named superclass,
the get_age function is simply called using branch with link as no polymorphic operations are necessary.
This method located at 0x400200 is called here at:
  400180:	94000020 	bl	0x400200                                // branch with link to 0x400200 - JUMP2

Additionally, the print_name method is called without going through the virtual table in a few instances.
It is called as such when printing "I am ", "!", "goo goo", and the error message for incorrect arg count.
This branch call occurs at 0x400138, 0x400144, 0x400174, 0x4001ec.
  400138:	17ffffde 	b	0x4000b0                                  // branch to 0x4000b0 - JUMP22 (print goo goo)
  400144:	97ffffdb 	bl	0x4000b0                                // branch with link to 0x4000b0 - JUMP12 (print I am )
  400174:	97ffffcf 	bl	0x4000b0                                // branch with link to 0x4000b0 - JUMP20 (print ERROR)
  4001ec:	17ffffb1 	b	0x4000b0                                  // branch to 0x4000b0 - JUMP17 (print !)
----------------------------------------------------------------------------------

Q12. Explain using pseudocode exactly how the Person object constructor works. Again, explanations at assembly level will not be accepted.

A subclass like Person inherits all the members from its superclass, however constructors are not members and thus not inherited.
It should be noted that the constructor of the superclass can be invoked from the subclass,
which is the process used to extend(inherit) the members of the superclass Named in this case.
When an object is created, the constructor method is automatically executed, assigning values to the object's members.
In this case, it invokes the superclass constructor to inherit the members(fields and methods),
and allocates a block of memory for members to initialize.
----------------------------------------------------------------------------------

Q13. Suppose you extended the Person class to implement a CuriousPerson class. The latter has an additional field called interest, and an additional method called print_interest. Based on the ABI you discovered, list the object layout of a CuriousPerson and its virtual table; in both cases include what is at each offset relative to the start of the object (or vtable).

(each class has constructors but not sure if I should include them here)

Assuming the subclass CuriousPerson was instanced in an object allocated on the stack A:
Since ./task3 is taken as an argument stored in stack too (at A+8),
the field names are populated first as args, followed by the methods further up the stack.

Class: CuriousPerson A+16
    twice-inherited field name A+24
    twice-inherited method print_name A+48
    inherited field age A+32
    inherited method get_age A+56
    field interest A+40
    method print_interest A+64
----------------------------------------------------------------------------------