From b36bb35c751436bde34d7eb3eee5d9aafec83679 Mon Sep 17 00:00:00 2001 From: Miao Date: Tue, 4 Jul 2023 16:09:23 +0000 Subject: [PATCH] done with homework04 --- hw04/README.md | 38 +++++++++++++---- hw04/bubblesort.c | 13 ++++++ hw04/bubblesort.ys | 50 ++++++++++++++++++++++ hw04/bubblesort_nojump.ys | 50 ++++++++++++++++++++++ hw04/bubblesort_onlycmov.ys | 63 +++++++++++++++++++++++++++ hw04/switchv.ys | 85 +++++++++++++++++++++++++++++++++++++ 6 files changed, 290 insertions(+), 9 deletions(-) create mode 100644 hw04/bubblesort.c create mode 100644 hw04/bubblesort.ys create mode 100644 hw04/bubblesort_nojump.ys create mode 100644 hw04/bubblesort_onlycmov.ys create mode 100644 hw04/switchv.ys diff --git a/hw04/README.md b/hw04/README.md index f7e9c6f..6e80111 100644 --- a/hw04/README.md +++ b/hw04/README.md @@ -1,15 +1,35 @@ #### 4.45 +A. No, the code sequence given does not correctly describe the behavior of the instruction `pushq %rsp`. + +The pushq instruction is specifically designed to push the value of a register onto the stack, and it performs the necessary stack pointer adjustment automatically. When the source register is `%rsp`, the behavior of the `pushq %rsp` instruction is different from the general case. It does not decrement the stack pointer before storing the value of `%rsp` on the stack. + +B. +``` +movq REG -8(%rsp) +subq $8, %rsp +``` #### 4.46 +A. No, the code sequence does not correctly describe the behavior of the instruction `popq %rsp`. + +The `popq` instruction is specifically designed to pop a value from the stack and store it in a register, and it performs the necessary stack pointer adjustment automatically. When the destination register is `%rsp`, the behavior of the `popq %rsp` instruction is different from the general case. It does not increment the stack pointer after copying the value from the stack to `%rsp`. + +B. +``` +addq $8, %rsp +movq 8(%rsp), REG +``` + #### 4.47 +See file `bubblesort.c` and `bubblesort.ys` + #### 4.48 +See file `bubblesort_nojump.ys` + #### 4.49 +See file `bubblesort_onlycmov.ys` + #### 4.50 -#### 4.51 -#### 4.52 -#### 4.53 -#### 4.54 -#### 4.55 -#### 4.56 -#### 4.57 -#### 4.58 -#### 4.59 \ No newline at end of file +See file `switchv.ys` + +#### 4.51 - 4.59 +See the lab material \ No newline at end of file diff --git a/hw04/bubblesort.c b/hw04/bubblesort.c new file mode 100644 index 0000000..32aab08 --- /dev/null +++ b/hw04/bubblesort.c @@ -0,0 +1,13 @@ +/* Bubble sort: Pointer version */ +void bubble_p(long *data, long count) { + long i, last; + for (last = count - 1; last > 0; --last) { + for (i = 0; i < last; ++i) { + if (*(data + i + 1) < *(data + i)) { + long t = *(data + i + 1); + *(data + i + 1) = *(data + i); + *(data + i) = t; + } + } + } +} \ No newline at end of file diff --git a/hw04/bubblesort.ys b/hw04/bubblesort.ys new file mode 100644 index 0000000..ddaae4d --- /dev/null +++ b/hw04/bubblesort.ys @@ -0,0 +1,50 @@ +# Y86-64 program to perform bubblesort + +# Function: bubble_p +# Arguments: +# %rdi: Pointer to the array +# %rsi: Number of elements in the array +bubble_p: + irmovq $0, %r8 # Initialize outer loop counter + +outer_loop: + irmovq $0, %r9 # Initialize inner loop counter + irmovq -8(%rsi), %r10 # Initialize last + +inner_loop: + addq $1, %r9 # Increment inner loop counter + cmpq %r10, %r9 # Compare inner loop counter with last + jg done_inner_loop # Exit inner loop if inner loop counter > last + + mrmovq (%rdi,%r9,8), %r11 # Load data[i+1] into %r11 + mrmovq (%rdi,%r9), %r12 # Load data[i] into %r12 + cmpq %r11, %r12 # Compare data[i+1] with data[i] + jge next_iteration # Skip swapping if data[i+1] >= data[i] + + rrmovq %r11, %r13 # Move data[i+1] to %r13 + rmmovq %r12, (%rdi,%r9,8) # Store data[i] into data[i+1] + rmmovq %r13, (%rdi,%r9) # Store data[i+1] into data[i] + +next_iteration: + jmp inner_loop # Jump to next iteration of inner loop + +done_inner_loop: + addq $1, %r8 # Increment outer loop counter + irmovq $8, %r14 # Initialize constant 8 + subq %r14, %rsi # Decrement last by 1 + + cmpq $0, %r8 # Compare outer loop counter with 0 + jg outer_loop # Jump to next iteration of outer loop if counter > 0 + + ret + +# Test code +.pos 0 +irmovq $arr, %rdi # Pass the array address as argument +irmovq $5, %rsi # Pass the number of elements as argument +call bubble_p # Call bubble_p function + +# Data +.pos 0x100 +arr: + .quad 5, 4, 3, 2, 1 diff --git a/hw04/bubblesort_nojump.ys b/hw04/bubblesort_nojump.ys new file mode 100644 index 0000000..8edd291 --- /dev/null +++ b/hw04/bubblesort_nojump.ys @@ -0,0 +1,50 @@ +# Y86-64 program to perform bubblesort with no jumps and at most three conditional moves + +# Function: bubble_p +# Arguments: +# %rdi: Pointer to the array +# %rsi: Number of elements in the array +bubble_p: + irmovq $0, %r8 # Initialize outer loop counter + +outer_loop: + irmovq $0, %r9 # Initialize inner loop counter + irmovq -8(%rsi), %r10 # Initialize last + +inner_loop: + addq $1, %r9 # Increment inner loop counter + cmpq %r10, %r9 # Compare inner loop counter with last + jg done_inner_loop # Exit inner loop if inner loop counter > last + + mrmovq (%rdi,%r9,8), %r11 # Load data[i+1] into %r11 + mrmovq (%rdi,%r9), %r12 # Load data[i] into %r12 + cmpq %r11, %r12 # Compare data[i+1] with data[i] + cmovl %r11, %r13 # Move data[i+1] to %r13 if less + cmovl %r12, %r11 # Move data[i] to %r11 if less + cmovl %r13, %r12 # Move data[i+1] to %r12 if less + + rmmovq %r11, (%rdi,%r9) # Store data[i] into data[i+1] + rmmovq %r12, (%rdi,%r9,8) # Store data[i+1] into data[i] + + jmp inner_loop # Jump to next iteration of inner loop + +done_inner_loop: + addq $1, %r8 # Increment outer loop counter + irmovq $8, %r14 # Initialize constant 8 + subq %r14, %rsi # Decrement last by 1 + + cmpq $0, %r8 # Compare outer loop counter with 0 + jg outer_loop # Jump to next iteration of outer loop + + ret + +# Test code +.pos 0 +irmovq $arr, %rdi # Pass the array address as argument +irmovq $5, %rsi # Pass the number of elements as argument +call bubble_p # Call bubble_p function + +# Data +.pos 0x100 +arr: + .quad 5, 4, 3, 2, 1 diff --git a/hw04/bubblesort_onlycmov.ys b/hw04/bubblesort_onlycmov.ys new file mode 100644 index 0000000..6b4de24 --- /dev/null +++ b/hw04/bubblesort_onlycmov.ys @@ -0,0 +1,63 @@ +# Y86-64 program to perform bubblesort using no jumps and just one conditional move +# In this modified version, the swapping of `data[i]` and `data[i+1]` is achieved +# using three XOR operations, which effectively swaps the values in `%r13` and `%r14`. +# This eliminates the need for jumps in the swapping logic. + +# Function: bubble_p +# Arguments: +# %rdi: Pointer to the array +# %rsi: Number of elements in the array +bubble_p: + irmovq $0, %r8 # Initialize outer loop counter + +outer_loop: + irmovq $0, %r9 # Initialize inner loop counter + irmovq -8(%rsi), %r10 # Initialize last + +inner_loop: + addq $1, %r9 # Increment inner loop counter + cmpq %r10, %r9 # Compare inner loop counter with last + jg done_inner_loop # Exit inner loop if inner loop counter > last + + mrmovq (%rdi,%r9,8), %r11 # Load data[i+1] into %r11 + mrmovq (%rdi,%r9), %r12 # Load data[i] into %r12 + cmpq %r11, %r12 # Compare data[i+1] with data[i] + jge next_iteration # Skip swapping if data[i+1] >= data[i] + + xorq %r13, %r13 # Clear %r13 (temporary register) + xorq %r14, %r14 # Clear %r14 (temporary register) + + # Swap data[i] and data[i+1] + rrmovq %r12, %r13 # Move data[i] to %r13 + rrmovq %r11, %r14 # Move data[i+1] to %r14 + xorq %r12, %r13 # XOR swap: %r13 = %r13 XOR %r12 + xorq %r11, %r14 # XOR swap: %r14 = %r14 XOR %r11 + xorq %r12, %r13 # XOR swap: %r13 = %r13 XOR %r12 + rmmovq %r13, (%rdi,%r9,8) # Store %r13 (data[i]) into data[i+1] + rmmovq %r14, (%rdi,%r9) # Store %r14 (data[i+1]) into data[i] + +next_iteration: + jmp inner_loop # Jump to next iteration of inner loop + +done_inner_loop: + addq $1, %r8 # Increment outer loop counter + irmovq $8, %r15 # Initialize constant 8 + subq %r15, %rsi # Decrement last by 1 + + cmpq $0, %r8 # Compare outer loop counter with 0 + jg outer_loop # Jump to next iteration of outer loop if counter > 0 + + ret + +# Test code +.pos 0 +irmovq $arr, %rdi # Pass the array address as argument +irmovq $5, %rsi # Pass the number of elements as argument +call bubble_p # Call bubble_p function + +# Data +.pos 0x100 +arr: + .quad 5, 4, 3, + +2, 1 diff --git a/hw04/switchv.ys b/hw04/switchv.ys new file mode 100644 index 0000000..760562f --- /dev/null +++ b/hw04/switchv.ys @@ -0,0 +1,85 @@ +# Y86-64 program to implement switchv using a jump table + +# Function: switchv +# Arguments: +# %rdi: idx - The value to switch on +# Returns: +# %rax: result - The result based on the switch cases +switchv: + irmovq $0x0, %rax # Initialize result to 0 + + irmovq $8, %rdx # Compute the offset for jump table indexing + imulq %rdx, %rdi + + irmovq $jt, %rdx # Load jump table address into %rdx + addq %rdi, %rdx # Add offset to jump table address + + mrmovq (%rdx), %rdx # Load address from jump table based on idx + pushq %rdx # Push computed address onto the stack + + ret # Return, effectively jumping to the computed address + +# Jump table +jt: + .quad case_0 # Address of case 0 + .quad default_case # Address of default case + .quad case_2_5 # Address of case 2 and 5 + .quad case_3 # Address of case 3 + +# Test code +.pos 0 +irmovq $CNT, %rcx # Counter for the loop +irmovq $MINVAL, %rax # Initialize MINVAL + +loop: + pushq %rcx # Push counter onto the stack + + irmovq $0, %rdi # Clear %rdi + irmovq $0xaaa, %rax # Set result to 0xaaa + cmpq $0, %rax # Compare result with 0 + je common_case # Jump to common case if result is 0 + + irmovq $8, %rdx # Compute the offset for jump table indexing + imulq %rdx, %rax # Multiply offset by result + + irmovq $jt, %rdx # Load jump table address into %rdx + addq %rax, %rdx # Add offset to jump table address + + mrmovq (%rdx), %rdx # Load address from jump table based on result + pushq %rdx # Push computed address onto the stack + + jmp handle_result # Jump to handle_result + +case_0: + rmmovq %rax, (%rsp) # Store result on the stack + irmovq $1, %rcx # Set counter to 1 + jmp loop_end # Jump to loop_end + +case_2_5: + rmmovq %rax, (%rsp) # Store result on the stack + irmovq $2, %rcx # Set counter to 2 + jmp loop_end # Jump to loop_end + +case_3: + rmmovq %rax, (%rsp) # Store result on the stack + irmovq $3, %rcx # Set counter to 3 + jmp loop_end # Jump to loop_end + +default_case: + rmmovq %rax, (%rsp) # Store result on the stack + irmovq $4, %rcx # Set counter to 4 + jmp loop_end # Jump to loop_end + +common_case: + irmovq $0xbbb, %rax # Set result to 0xbbb + +handle_result: + rmmovq %rax, (%rsp) # Store result on the stack + irmovq $1, %rcx # Set counter to 1 + +loop_end: + irmovq $0x8, %rdi # Set increment value to 8 + addq %rdi, %rsp # Increment stack pointer + + popq %rdi # Pop the computed address into %rdi + ret # Return, effectively jumping to the computed address