college/Fall-2024/CS-3843/Assignments/7/Assignment.typ
2024-11-03 13:34:46 -06:00

353 lines
8.8 KiB
Plaintext

#show link: set text(blue)
#set text(font: "Calibri")
#show raw: set text(font: "Fira Code")
#set table.cell(breakable: false)
#set table(stroke: (x, y) => (
left: if x > 0 {
.1pt
},
top: if y == 1 {
0.5pt
} else if y > 1 {
0.1pt
},
))
#set page(margin: (x: .25in, y: .25in))
#let solve(solution) = {
block(
inset: 3pt,
stroke: blue + .3pt,
fill: rgb(0, 149, 255, 15%),
radius: 4pt,
)[#solution]
}
#let solvein(solution) = {
let outset = 3pt
h(outset)
box(
outset: outset,
stroke: blue + .3pt,
fill: rgb(0, 149, 255, 15%),
radius: 4pt,
)[#solution]
}
#let note(content) = {
block(
inset: 3pt,
stroke: luma(20%) + .3pt,
fill: luma(95%),
radius: 4pt,
)[#content]
}
#let notein(content) = {
let outset = 3pt
h(outset)
box(
outset: outset,
stroke: luma(20%) + .3pt,
fill: luma(95%),
radius: 4pt,
)[#content]
}
#align(center)[
= CS 3843 Computer Organization
HW 7\
#underline[Price Hiller] *|* #underline[zfp106]
]
#line(length: 100%, stroke: .25pt)
1. (18 points) Show your work. Show how you compute memory addresses by using the effective memory address computation.
Assume the following values are stored at the indicated memory addresses and registers:
#table(
inset: (
x: 15pt,
),
columns: (auto, auto, auto, auto),
table.header(
[Address],
[Value],
[Register],
[Value],
),
[`0x100`], [`0xFF`], [`%rax`], [`0x100`],
[`0x104`], [`0xAB`], [`%rcx`], [`0x1`],
[`0x108`], [`0x13`], [`%rdx`], [`0x3`],
[`0x10C`], [`0x11`], [``], [``],
)
Fill in the following table showing the values for indicated operands:
#table(
inset: (
x: 15pt,
),
columns: (auto, auto, auto),
table.header(
[Operand],
[Value],
[Work],
),
[`%rax`],
solve[`0x100`],
note[
+ `%rax`
+ `0x100`
],
[`0x104`],
solve[`0xAB`],
note[
+ `0x104`
+ `0xAB`
],
[`$0x108`],
solve[`0x108`],
note[
+ `$0x108`
+ `0x108`
],
[`(%rax)`],
solve[`0xFF`],
note[
+ `(%rax)`
+ `(0x100)`
+ `0xFF`
],
[`4(%rax)`],
solve[`0xAB`],
note[
+ `4(%rax)`
+ `(%rax + 4)`
+ `(0x100 + 4)`
+ `(0x104)`
+ `0xAB`
],
[`9(%rax,%rdx)`],
solve[`0x11`],
note[
+ `9(%rax,%rdx)`
+ `(%rax + %rdx + 9)`
+ `(0x100 + 0x3 + 9)`
+ `(0x10C)`
+ `0x11`
],
[`260(%rcx,%rdx)`],
solve[`0x11`],
note[
+ `260(%rcx,%rdx)`
+ `(%rcx + %rdx + 260)`
+ `(%rcx + %rdx + 0x104)`
+ `(0x1 + 0x3 + 0x104)`
+ `(0x108)`
+ `0x13`
],
[`0xFC(,%rcx,4)`],
solve[`0x104`],
note[
+ `0xFC(,%rcx,4)`
+ `(%rcx * 4 + 0xFC)`
+ `(0x1 * 4 + 0xFC)`
+ `(0x4 + 0xFC)`
+ `(0x100)`
+ `0xFF`
],
[`(%rax,%rdx,4)`],
solve[`0x10C`],
note[
+ `(%rax,%rdx,4)`
+ `(%rax + %rdx * 4)`
+ `(0x100 + 0x3 * 4)`
+ `(0x100 + 0xC)`
+ `(0x10C)`
+ `0x11`
],
)
2. (12 points) Explain for each line why you chose a certain suffix such as `b`, `w`, `l`, or `q`.
For each of the following lines of assembly language, determine the appropriate instruction suffix based on the operands. (For example `mov` can be written as `movb`, `movw`, `movl`, or `movq`.)
#align(center)[#note[My reasoning? My reasoning is that ChatGPT said so. _Just kidding ;)_.]]
#table(
inset: (
x: 15pt,
),
columns: (auto, auto),
table.header(
[Line],
[Reasoning],
),
[`mov`#solvein[`l`] ` %eax, (%rsp)`],
[#note[Because we're moving into a memory location pointed to by `%rsp`, we want to focus on the size of `%eax`. `%eax` is a 4 byte register, so we want an instruction that operates on double words, so our suffix will be an `l`.]],
[`mov`#solvein[`w`] ` (%rax), %dx`],
[#note[We're moving from a value pointed to by an 8 byte register into a 2 byte register. 2 bytes is a word, so we want to use a single word length instruction which is suffixed by a `w`.]],
[`mov`#solvein[`b`] ` $0xFF, %bl`],
[#note[Here we have a raw hex value representing a singe byte, `1111 1111`, and we're moving it into a single byte length register so we'll want to use a byte length instruction which is suffixed by a `b`.]],
[`mov`#solvein[`b`] ` (%rsp,%rdx,4), %dl`],
[#note[Importantly, we are moving a value into `%dl` which is a single byte length; therefore, we want to use a single byte length instruction which is suffixed by a `b`.]],
[`mov`#solvein[`q`] ` (%rdx), %rax`],
[#note[Since we're moving a value pointed to by an 8 byte register into an 8 byte register, we'll want to use a quad word length instruction which is suffixed by a `q`.]],
[`mov`#solvein[`w`] ` %dx, (%rax)`],
[#note[Because `(%rax)` is is a larger register than `%dx`, the only register that matters here is `%dx`. `%dx` can store 2 bytes which is a single word, so we should use a word length instruction, that begin suffixed by `w`.]],
)
3. (14 points) Explain for answer for each line:
Each of the following lines of code generates an error message when we invoke the assembler. Explain the what is wrong with each line.
#table(
inset: (
x: 15pt,
),
columns: (auto, auto),
table.header(
[Code],
[Why it's wrong],
),
[`movb $0xF, (%ebx)`],
[#solve[This shouldn't be moving `$0xF` into the memory pointed to by `%ebx` as `(%ebx)` cannot be used as an address register in this context. Removing the parentheses would make it somewhat more valid.]],
[`movl %rax, (%rsp)`],
[#solve[The `l` suffix is intended to move 4 bytes, both `%rax` and `%rsp` are 8 bytes in size and thus `movl` is moving the wrong number of bytes.]],
[`movw (%rax),4(%rsp)`],
[#solve[Same issue as the previous one. The `w` suffix is intended to move 2 bytes, but both `%rax` and `%rsp` are 8 bytes in size and thus we have a operand size mismatch.]],
[`movb %al,%sl`],
[#solve[There is no such register `%sl`, there's `%si` or `%sil`, but not `%sl`.]],
[`movq %rax,$0x123`],
[#solve[We cannot have an *immediate* as a destination to move a value into.]],
[`movl %eax,%rdx`],
[#solve[Attempting to move a 4 byte value into an 8 byte register may lead to data loss. We should use an opcode that clears the upper bits of `%rdx`, like `movslq`.]],
[`movb %si, 8(%rbp)`],
[#solve[This is attempting to move a 2 byte value using a 1 byte opcode. Instead of `movb` we should use `movw`.]],
)
4. (12 points) Show your work for each instruction. Show how you compute effective memory addresses.
Assume the following values are stored at the indicated memory addresses and registers:
#table(
inset: (
x: 15pt,
),
columns: (auto, auto, auto, auto),
table.header(
[Address],
[Value],
[Register],
[Value],
),
[`0x100`], [`0xFF`], [`%rax`], [`0x100`],
[`0x108`], [`0xAB`], [`%rcx`], [`0x1`],
[`0x110`], [`0x13`], [`%rdx`], [`0x3`],
[`0x118`], [`0x11`], [``], [``],
)
Fill in the following table showing the effects of the following instructions, in terms of both register or memory location what will be updated and the resulting value:
#table(
inset: (
x: 15pt,
),
columns: (auto, auto, auto, auto),
table.header(
[Instruction],
[Destination],
[Value],
[Work],
),
[`addq %rcx,(%rax)`],
solve[`0x100`],
solve[`0x100`],
note[
+ `(%rax) = %rcx + (%rax)`
+ `(0x100) = 0x1 + (0x100)`
+ `(0x100) = 0x1 + 0xFF`
+ `(0x100) = 0x100`
],
[`subq %rdx,8(%rax)`],
solve[`0x108`],
solve[`0xA8`],
note[
+ `8(%rax) = 8(%rax) - %rdx`
+ `(0x100 + 8) = (0x100 + 8) - 0x3`
+ `(0x108) = (0x108) - 0x3`
+ `(0x108) = 0xAB - 0x3`
+ `(0x108) = 0xA8`
],
[`imulq $16,(%rax,%rdx,8)`],
solve[`0x118`],
solve[`0x110`],
note[
+ `(%rax,%rdx,8) = (%rax,%rdx,8) * 16`
+ `(0x100,0x3,8) = (0x100,0x3,8) * 16`
+ `(0x100 + 0x3 * 8) = (0x100 + 0x3 * 8) * 16`
+ `(0x100 + 0x18) = (0x100 + 0x18) * 16`
+ `(0x118) = (0x118) * 16`
+ `(0x118) = 0x11 * 16`
+ `(0x118) = 0x110`
],
[`incq 16(%rax)`],
solve[`0x110`],
solve[`0x14`],
note[
+ `16(%rax) = 16(%rax) + 1`
+ `16(0x100) = 16(0x100) + 1`
+ `(0x100 + 16) = (0x100 + 16) + 1`
+ `(0x110) = (0x110) + 1`
+ `(0x110) = 0x13 + 1`
+ `(0x110) = 0x14`
],
[`decq %rcx`],
solve[`%rcx`],
solve[`0x0`],
note[
+ `%rcx = %rcx - 1`
+ `%rcx = 0x1 - 1`
+ `%rcx = 0x0`
],
[`subq %rdx,%rax`],
solve[`%rax`],
solve[`0xFD`],
note[
+ `%rax = %rax - %rdx`
+ `%rax = 0x100 - 0x3`
+ `%rax = 0xFD`
],
)